brooklyn-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From aleds...@apache.org
Subject [2/3] brooklyn-server git commit: BROOKLYN-380: Adds DynamicFabric.includeInitialChildren config
Date Tue, 08 Nov 2016 21:01:38 GMT
BROOKLYN-380: Adds DynamicFabric.includeInitialChildren config

And adds tests for existing behaviour.


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

Branch: refs/heads/master
Commit: a757cdfe4564ab41293edd0a52fb60be7ac4886a
Parents: e56de02
Author: Aled Sage <aled.sage@gmail.com>
Authored: Fri Nov 4 12:50:53 2016 +0000
Committer: Aled Sage <aled.sage@gmail.com>
Committed: Tue Nov 8 11:26:35 2016 +0000

----------------------------------------------------------------------
 .../brooklyn/entity/group/DynamicFabric.java    |  23 ++--
 .../entity/group/DynamicFabricImpl.java         |  61 ++++++---
 .../entity/group/DynamicRegionsFabricTest.java  | 123 +++++++++++++++++--
 3 files changed, 174 insertions(+), 33 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/a757cdfe/core/src/main/java/org/apache/brooklyn/entity/group/DynamicFabric.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/entity/group/DynamicFabric.java b/core/src/main/java/org/apache/brooklyn/entity/group/DynamicFabric.java
index 943ed9b..92b9621 100644
--- a/core/src/main/java/org/apache/brooklyn/entity/group/DynamicFabric.java
+++ b/core/src/main/java/org/apache/brooklyn/entity/group/DynamicFabric.java
@@ -42,29 +42,38 @@ import com.google.common.reflect.TypeToken;
 @SuppressWarnings("serial")
 public interface DynamicFabric extends AbstractGroup, Startable, Fabric {
 
-    public static final AttributeSensor<Integer> FABRIC_SIZE = Sensors.newIntegerSensor("fabric.size",
"Fabric size");
+    ConfigKey<Boolean> INCLUDE_INITIAL_CHILDREN = ConfigKeys.newBooleanConfigKey(
+            "includeInitialChildren",
+            "Whether to include the initial children when handing out the locations to new
members "
+                    + "(i.e. if true, these children will each be given a location (round-robin),
"
+                    + "rather than creating new members; if false then the children will
be given "
+                    + "just the first location (if any), and new members will be created
dynamically "
+                    + "for each given location).",
+            true);
     
     @SetFromFlag("memberSpec")
-    public static final ConfigKey<EntitySpec<?>> MEMBER_SPEC = ConfigKeys.newConfigKey(
+    ConfigKey<EntitySpec<?>> MEMBER_SPEC = ConfigKeys.newConfigKey(
             new TypeToken<EntitySpec<?>>() {}, "dynamiccfabric.memberspec", "entity
spec for creating new cluster members", null);
 
     @SetFromFlag("factory")
-    public static final ConfigKey<EntityFactory<?>> FACTORY = ConfigKeys.newConfigKey(
+    ConfigKey<EntityFactory<?>> FACTORY = ConfigKeys.newConfigKey(
         new TypeToken<EntityFactory<?>>() {}, "dynamicfabric.factory", "factory
for creating new cluster members", null);
 
     @SetFromFlag("displayNamePrefix")
-    public static final ConfigKey<String> DISPLAY_NAME_PREFIX = ConfigKeys.newStringConfigKey(
+    ConfigKey<String> DISPLAY_NAME_PREFIX = ConfigKeys.newStringConfigKey(
             "dynamicfabric.displayNamePrefix", "Display name prefix, for created children");
 
     @SetFromFlag("displayNameSuffix")
-    public static final ConfigKey<String> DISPLAY_NAME_SUFFIX = ConfigKeys.newStringConfigKey(
+    ConfigKey<String> DISPLAY_NAME_SUFFIX = ConfigKeys.newStringConfigKey(
             "dynamicfabric.displayNameSuffix", "Display name suffix, for created children");
 
     @SetFromFlag("customChildFlags")
-    public static final MapConfigKey<Object> CUSTOM_CHILD_FLAGS = new MapConfigKey<Object>(
+    MapConfigKey<Object> CUSTOM_CHILD_FLAGS = new MapConfigKey<Object>(
             Object.class, "dynamicfabric.customChildFlags", "Additional flags to be passed
to children when they are being created", ImmutableMap.<String,Object>of());
 
-    public static final AttributeSensor<Lifecycle> SERVICE_STATE_ACTUAL = Attributes.SERVICE_STATE_ACTUAL;
+    AttributeSensor<Integer> FABRIC_SIZE = Sensors.newIntegerSensor("fabric.size",
"Fabric size");
+    
+    AttributeSensor<Lifecycle> SERVICE_STATE_ACTUAL = Attributes.SERVICE_STATE_ACTUAL;
 
     public void setMemberSpec(EntitySpec<?> memberSpec);
     

http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/a757cdfe/core/src/main/java/org/apache/brooklyn/entity/group/DynamicFabricImpl.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/entity/group/DynamicFabricImpl.java b/core/src/main/java/org/apache/brooklyn/entity/group/DynamicFabricImpl.java
index 34051c5..a02d797 100644
--- a/core/src/main/java/org/apache/brooklyn/entity/group/DynamicFabricImpl.java
+++ b/core/src/main/java/org/apache/brooklyn/entity/group/DynamicFabricImpl.java
@@ -110,6 +110,8 @@ public class DynamicFabricImpl extends AbstractGroupImpl implements DynamicFabri
     
     @Override
     public void start(Collection<? extends Location> locsO) {
+        boolean includeInitialChildren = Boolean.TRUE.equals(config().get(INCLUDE_INITIAL_CHILDREN));
+        
         addLocations(locsO);
         List<Location> locationsToStart = MutableList.copyOf(Locations.getLocationsCheckingAncestors(locsO,
this));
         
@@ -122,27 +124,50 @@ public class DynamicFabricImpl extends AbstractGroupImpl implements
DynamicFabri
         try {
             Map<Entity, Task<?>> tasks = Maps.newLinkedHashMap();
             
-            // first look at existing Startable children - start them with the locations
passed in here,
-            // if they have no locations yet
-            for (Entity child: getChildren()) {
-                if (child instanceof Startable) {
-                    addMember(child);
-                    Location it = null;
-                    if (child.getLocations().isEmpty())
-                        // give him any of these locations if he has none, allowing round
robin here
-                        if (!locationsToStart.isEmpty()) {
-                            it = locationsToStart.get(locIndex++ % locationsToStart.size());
-                            ((EntityInternal)child).addLocations(Arrays.asList(it));
+            if (includeInitialChildren) {
+                // first look at existing Startable children - start them with the locations
passed in here,
+                // if they have no locations yet
+                for (Entity child: getChildren()) {
+                    if (child instanceof Startable) {
+                        addMember(child);
+                        Location it = null;
+                        if (child.getLocations().isEmpty()) {
+                            // give him any of these locations if he has none, allowing round
robin here
+                            if (!locationsToStart.isEmpty()) {
+                                it = locationsToStart.get(locIndex++ % locationsToStart.size());
+                                ((EntityInternal)child).addLocations(Arrays.asList(it));
+                            }
+                        }
+                        
+                        tasks.put(child, Entities.submit(this,
+                            Effectors.invocation(child, START, ImmutableMap.of("locations",

+                                it==null ? ImmutableList.of() : ImmutableList.of(it))).asTask()));
+                    }
+                }
+                // remove all the locations we applied to existing nodes
+                while (locIndex-->0 && !locationsToStart.isEmpty())
+                    locationsToStart.remove(0);
+                
+            } else {
+                // Start the existing children, but don't count that as "consuming" the initial
+                // locations.
+                for (Entity child : getChildren()) {
+                    if (child instanceof Startable) {
+                        Location it = null;
+                        if (child.getLocations().isEmpty()) {
+                            // give him the first location
+                            if (!locationsToStart.isEmpty()) {
+                                it = locationsToStart.get(0);
+                                ((EntityInternal)child).addLocations(Arrays.asList(it));
+                            }
                         }
-                    
-                    tasks.put(child, Entities.submit(this,
-                        Effectors.invocation(child, START, ImmutableMap.of("locations", 
-                            it==null ? ImmutableList.of() : ImmutableList.of(it))).asTask()));
+                        
+                        tasks.put(child, Entities.submit(this,
+                            Effectors.invocation(child, START, ImmutableMap.of("locations",

+                                it==null ? ImmutableList.of() : ImmutableList.of(it))).asTask()));
+                    }
                 }
             }
-            // remove all the locations we applied to existing nodes
-            while (locIndex-->0 && !locationsToStart.isEmpty())
-                locationsToStart.remove(0);
 
             // finally (and usually) we create new entities for locations passed in
             // (unless they were consumed by pre-existing children which didn't have locations)

http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/a757cdfe/core/src/test/java/org/apache/brooklyn/entity/group/DynamicRegionsFabricTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/brooklyn/entity/group/DynamicRegionsFabricTest.java
b/core/src/test/java/org/apache/brooklyn/entity/group/DynamicRegionsFabricTest.java
index c54bb3a..5227c8d 100644
--- a/core/src/test/java/org/apache/brooklyn/entity/group/DynamicRegionsFabricTest.java
+++ b/core/src/test/java/org/apache/brooklyn/entity/group/DynamicRegionsFabricTest.java
@@ -19,6 +19,8 @@
 package org.apache.brooklyn.entity.group;
 
 import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertFalse;
+import static org.testng.Assert.assertTrue;
 
 import java.util.Collection;
 import java.util.List;
@@ -27,10 +29,12 @@ import java.util.Set;
 import org.apache.brooklyn.api.entity.Entity;
 import org.apache.brooklyn.api.entity.EntitySpec;
 import org.apache.brooklyn.api.location.Location;
+import org.apache.brooklyn.core.entity.BrooklynConfigKeys;
 import org.apache.brooklyn.core.location.SimulatedLocation;
 import org.apache.brooklyn.core.test.BrooklynAppUnitTestSupport;
+import org.apache.brooklyn.core.test.entity.TestApplication;
 import org.apache.brooklyn.core.test.entity.TestEntity;
-import org.apache.brooklyn.entity.group.DynamicRegionsFabric;
+import org.apache.brooklyn.entity.stock.BasicEntity;
 import org.apache.brooklyn.util.collections.MutableSet;
 import org.apache.brooklyn.util.exceptions.Exceptions;
 import org.testng.annotations.BeforeMethod;
@@ -60,16 +64,98 @@ public class DynamicRegionsFabricTest extends BrooklynAppUnitTestSupport
{
     }
 
     @Test
-    public void testUsesInitialLocations() throws Exception {
+    public void testUsesInitialLocationsFromStartEffectorArgs() throws Exception {
         app.start(ImmutableList.of(loc1, loc2));
 
-        assertEquals(fabric.getChildren().size(), 2, "children="+fabric.getChildren());
-        assertEquals(fabric.getMembers().size(), 2, "members="+fabric.getMembers());
-        assertEqualsIgnoringOrder(fabric.getChildren(), fabric.getMembers());
-        assertEqualsIgnoringOrder(getLocationsOfChildren(fabric), ImmutableList.of(loc1,
loc2));
+        assertFabricChildren(fabric, 2, ImmutableList.of(loc1, loc2));
+    }
+    
+    @Test
+    @SuppressWarnings("deprecation")
+    public void testUsesInitialLocationsFromAppSpec() throws Exception {
+        TestApplication app2 = mgmt.getEntityManager().createEntity(EntitySpec.create(TestApplication.class)
+            .configure(BrooklynConfigKeys.SKIP_ON_BOX_BASE_DIR_RESOLUTION, true)
+            .child(EntitySpec.create(DynamicRegionsFabric.class)
+                .configure("memberSpec", EntitySpec.create(TestEntity.class)))
+            .locations(ImmutableList.of(loc1, loc2)));
+        DynamicRegionsFabric fabric2 = (DynamicRegionsFabric) Iterables.getOnlyElement(app2.getChildren());
+        app2.start(ImmutableList.<Location>of());
+        
+        assertFabricChildren(fabric2, 2, ImmutableList.of(loc1, loc2));
     }
     
     @Test
+    @SuppressWarnings("deprecation")
+    public void testUsesInitialLocationsFromEntitySpec() throws Exception {
+        TestApplication app2 = mgmt.getEntityManager().createEntity(EntitySpec.create(TestApplication.class)
+            .configure(BrooklynConfigKeys.SKIP_ON_BOX_BASE_DIR_RESOLUTION, true)
+            .child(EntitySpec.create(DynamicRegionsFabric.class)
+                .configure("memberSpec", EntitySpec.create(TestEntity.class))
+                .locations(ImmutableList.of(loc1, loc2))));
+        DynamicRegionsFabric fabric2 = (DynamicRegionsFabric) Iterables.getOnlyElement(app2.getChildren());
+        app2.start(ImmutableList.<Location>of());
+        
+        assertFabricChildren(fabric2, 2, ImmutableList.of(loc1, loc2));
+    }
+    
+    @Test
+    public void testUsesInitialLocationsForExistingChildCreatingExtras() throws Exception
{
+        // Expect existing child to be used for one location, and a second child to be created

+        // automatically for the second location
+        runUsesInitialLocationsForExistingChildren(1);
+    }
+
+    @Test
+    public void testUsesInitialLocationsForExistingChildren() throws Exception {
+        // Expect the two existing children to be used for the two locations; no additional
+        // children should be created automatically.
+        runUsesInitialLocationsForExistingChildren(2);
+    }
+
+    @Test
+    public void testUsesInitialLocationsRoundRobinForExistingChildren() throws Exception
{
+        // Expect the two locations to be used round-robin for the three existing children;
+        // no additional children should be created automatically.
+        runUsesInitialLocationsForExistingChildren(3);
+    }
+
+    @Test
+    public void testIgnoredNonStartableChildren() throws Exception {
+        // Add a basic entity; this will not count as a "member" because it is not startable.
+        // Therefore expect two new children to be created.
+        BasicEntity existingChild = fabric.addChild(EntitySpec.create(BasicEntity.class));
+        app.start(ImmutableList.of(loc1, loc2));
+        assertFabricMembers(fabric, 2, ImmutableList.of(loc1, loc2));
+        assertFalse(fabric.getMembers().contains(existingChild));
+    }
+
+    @Test
+    public void testTurnOffIncludeInitialChildren() throws Exception {
+        // Turning off "include initial children" means they will be ignored in the member-count.
+        fabric.config().set(DynamicFabric.INCLUDE_INITIAL_CHILDREN, false);
+        TestEntity existingChild = fabric.addChild(EntitySpec.create(TestEntity.class));
+        app.start(ImmutableList.of(loc1, loc2));
+        assertFabricMembers(fabric, 2, ImmutableList.of(loc1, loc2));
+        
+        assertFalse(fabric.getMembers().contains(existingChild));
+        assertEqualsIgnoringOrder(existingChild.getLocations(), ImmutableList.of(loc1));
+    }
+
+    protected void runUsesInitialLocationsForExistingChildren(int numChildren) throws Exception
{
+        List<TestEntity> existingChildren = Lists.newArrayList();
+        for (int i = 0; i < numChildren; i++) {
+            existingChildren.add(fabric.addChild(EntitySpec.create(TestEntity.class)));
+        }
+        app.start(ImmutableList.of(loc1, loc2));
+
+        int expectedNumChildren = Math.max(numChildren, 2);
+        Iterable<Location> expectedChildLocations = Iterables.limit(Iterables.cycle(ImmutableList.of(loc1,
loc2)), expectedNumChildren);
+        
+        assertFabricChildren(fabric, expectedNumChildren, ImmutableList.copyOf(expectedChildLocations));
+        assertTrue(fabric.getChildren().containsAll(existingChildren));
+    }
+
+    @Test
     public void testDynamicallyAddLocations() throws Exception {
         app.start(ImmutableList.of(loc1));
         Set<Entity> initialChildren = ImmutableSet.copyOf(fabric.getChildren());
@@ -156,9 +242,17 @@ public class DynamicRegionsFabricTest extends BrooklynAppUnitTestSupport
{
     }
     
     private List<Location> getLocationsOfChildren(DynamicRegionsFabric fabric) {
+        return getLocationsOf(fabric.getChildren());
+    }
+
+    private List<Location> getLocationsOfMembers(DynamicRegionsFabric fabric) {
+        return getLocationsOf(fabric.getMembers());
+    }
+
+    private List<Location> getLocationsOf(Iterable<? extends Entity> entities)
{
         List<Location> result = Lists.newArrayList();
-        for (Entity child : fabric.getChildren()) {
-            result.addAll(child.getLocations());
+        for (Entity entity : entities) {
+            result.addAll(entity.getLocations());
         }
         return result;
     }
@@ -167,4 +261,17 @@ public class DynamicRegionsFabricTest extends BrooklynAppUnitTestSupport
{
         assertEquals(Iterables.size(col1), Iterables.size(col2), "col2="+col1+"; col2="+col2);
         assertEquals(MutableSet.copyOf(col1), MutableSet.copyOf(col2), "col1="+col1+"; col2="+col2);
     }
+    
+    private void assertFabricChildren(DynamicRegionsFabric fabric, int expectedSize, List<?
extends Location> expectedLocs) {
+        assertEquals(fabric.getChildren().size(), expectedSize, "children="+fabric.getChildren());
+        assertEquals(fabric.getMembers().size(), expectedSize, "members="+fabric.getMembers());
+        assertEqualsIgnoringOrder(fabric.getChildren(), fabric.getMembers());
+        assertEqualsIgnoringOrder(getLocationsOfChildren(fabric), expectedLocs);
+    }
+    
+    private void assertFabricMembers(DynamicRegionsFabric fabric, int expectedSize, List<?
extends Location> expectedLocs) {
+        assertEquals(fabric.getMembers().size(), expectedSize, "members="+fabric.getMembers());
+        assertTrue(fabric.getChildren().containsAll(fabric.getMembers()));
+        assertEqualsIgnoringOrder(getLocationsOfMembers(fabric), expectedLocs);
+    }
 }


Mime
View raw message