add an optional config `firstMemberSpec` to DynamicCluster, with test
Project: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/repo Commit: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/commit/64b19928 Tree: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/tree/64b19928 Diff: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/diff/64b19928 Branch: refs/heads/master Commit: 64b19928d80bef311f3f1dfebfa075466aad82c7 Parents: 04fc801 Author: Alex Heneveld <[email protected]> Authored: Thu Apr 2 07:23:47 2015 -0400 Committer: Alex Heneveld <[email protected]> Committed: Sun Apr 12 20:00:52 2015 -0500 ---------------------------------------------------------------------- .../brooklyn/entity/group/DynamicCluster.java | 5 ++ .../entity/group/DynamicClusterImpl.java | 5 +- .../entity/group/DynamicClusterTest.java | 52 ++++++++++++++++++++ 3 files changed, 61 insertions(+), 1 deletion(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/64b19928/core/src/main/java/brooklyn/entity/group/DynamicCluster.java ---------------------------------------------------------------------- diff --git a/core/src/main/java/brooklyn/entity/group/DynamicCluster.java b/core/src/main/java/brooklyn/entity/group/DynamicCluster.java index 764704e..8309528 100644 --- a/core/src/main/java/brooklyn/entity/group/DynamicCluster.java +++ b/core/src/main/java/brooklyn/entity/group/DynamicCluster.java @@ -120,6 +120,11 @@ public interface DynamicCluster extends AbstractGroup, Cluster, MemberReplaceabl new TypeToken<EntitySpec<?>>() { }, "dynamiccluster.memberspec", "entity spec for creating new cluster members", null); + @SetFromFlag("firstMemberSpec") + ConfigKey<EntitySpec<?>> FIRST_MEMBER_SPEC = ConfigKeys.newConfigKey( + new TypeToken<EntitySpec<?>>() { }, + "dynamiccluster.firstmemberspec", "entity spec for creating new cluster members, used for the very first member if different", null); + /** @deprecated since 0.7.0; use {@link #MEMBER_SPEC} instead. */ @SuppressWarnings("rawtypes") @Deprecated http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/64b19928/core/src/main/java/brooklyn/entity/group/DynamicClusterImpl.java ---------------------------------------------------------------------- diff --git a/core/src/main/java/brooklyn/entity/group/DynamicClusterImpl.java b/core/src/main/java/brooklyn/entity/group/DynamicClusterImpl.java index 0b77910..43b671c 100644 --- a/core/src/main/java/brooklyn/entity/group/DynamicClusterImpl.java +++ b/core/src/main/java/brooklyn/entity/group/DynamicClusterImpl.java @@ -767,7 +767,10 @@ public class DynamicClusterImpl extends AbstractGroupImpl implements DynamicClus } protected Entity createNode(@Nullable Location loc, Map<?,?> flags) { - EntitySpec<?> memberSpec = getMemberSpec(); + EntitySpec<?> memberSpec = null; + if (getMembers().isEmpty()) memberSpec = getConfig(FIRST_MEMBER_SPEC); + if (memberSpec == null) memberSpec = getMemberSpec(); + if (memberSpec != null) { return addChild(EntitySpec.create(memberSpec).configure(flags).location(loc)); } http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/64b19928/core/src/test/java/brooklyn/entity/group/DynamicClusterTest.java ---------------------------------------------------------------------- diff --git a/core/src/test/java/brooklyn/entity/group/DynamicClusterTest.java b/core/src/test/java/brooklyn/entity/group/DynamicClusterTest.java index 8f953a4..58949d7 100644 --- a/core/src/test/java/brooklyn/entity/group/DynamicClusterTest.java +++ b/core/src/test/java/brooklyn/entity/group/DynamicClusterTest.java @@ -65,6 +65,7 @@ import brooklyn.test.EntityTestUtils; import brooklyn.test.entity.TestEntity; import brooklyn.test.entity.TestEntityImpl; import brooklyn.util.collections.MutableMap; +import brooklyn.util.collections.MutableSet; import brooklyn.util.collections.QuorumCheck.QuorumChecks; import brooklyn.util.exceptions.Exceptions; import brooklyn.util.time.Time; @@ -898,4 +899,55 @@ public class DynamicClusterTest extends BrooklynAppUnitTestSupport { return e; } } + + @Test + public void testDifferentFirstMemberSpec() throws Exception { + DynamicCluster cluster = app.createAndManageChild(EntitySpec.create(DynamicCluster.class) + .configure(DynamicCluster.FIRST_MEMBER_SPEC, + EntitySpec.create(BasicEntity.class).configure(TestEntity.CONF_NAME, "first")) + .configure(DynamicCluster.MEMBER_SPEC, + EntitySpec.create(BasicEntity.class).configure(TestEntity.CONF_NAME, "non-first")) + .configure(DynamicCluster.UP_QUORUM_CHECK, QuorumChecks.alwaysTrue()) + .configure(DynamicCluster.INITIAL_SIZE, 3)); + cluster.start(ImmutableList.of(loc)); + + EntityTestUtils.assertAttributeEqualsEventually(cluster, Attributes.SERVICE_STATE_ACTUAL, Lifecycle.RUNNING); + assertTrue(cluster.getAttribute(Attributes.SERVICE_UP)); + + assertEquals(cluster.getMembers().size(), 3); + + assertFirstAndNonFirstCounts(cluster.getMembers(), 1, 2); + + // and after re-size + cluster.resize(4); +// Entities.dumpInfo(cluster); + assertFirstAndNonFirstCounts(cluster.getMembers(), 1, 3); + + // and re-size to 1 + cluster.resize(1); + assertFirstAndNonFirstCounts(cluster.getMembers(), 1, 0); + + // and re-size to 0 + cluster.resize(0); + assertFirstAndNonFirstCounts(cluster.getMembers(), 0, 0); + + // and back to 3 + cluster.resize(3); + assertFirstAndNonFirstCounts(cluster.getMembers(), 1, 2); + } + + private void assertFirstAndNonFirstCounts(Collection<Entity> members, int expectedFirstCount, int expectedNonFirstCount) { + Set<Entity> found = MutableSet.of(); + for (Entity e: members) { + if ("first".equals(e.getConfig(TestEntity.CONF_NAME))) found.add(e); + } + assertEquals(found.size(), expectedFirstCount); + + found.clear(); + for (Entity e: members) { + if ("non-first".equals(e.getConfig(TestEntity.CONF_NAME))) found.add(e); + } + assertEquals(found.size(), expectedNonFirstCount); + } + }
