Adds PROVISION_LATCH config

Behaviour as other latches. Used in MachineLifecycleEffectorTasks.


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

Branch: refs/heads/master
Commit: 620e4c187666137c69396397805b6413716c2075
Parents: 9645e8c
Author: Sam Corbett <[email protected]>
Authored: Thu Jun 11 15:07:31 2015 +0100
Committer: Sam Corbett <[email protected]>
Committed: Thu Jun 11 15:07:31 2015 +0100

----------------------------------------------------------------------
 .../entity/basic/BrooklynConfigKeys.java        |  1 +
 software/base/pom.xml                           |  7 ++
 .../software/MachineLifecycleEffectorTasks.java |  3 +-
 .../MachineLifecycleEffectorTasksTest.java      | 82 ++++++++++++++++++++
 4 files changed, 92 insertions(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/620e4c18/core/src/main/java/brooklyn/entity/basic/BrooklynConfigKeys.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/entity/basic/BrooklynConfigKeys.java 
b/core/src/main/java/brooklyn/entity/basic/BrooklynConfigKeys.java
index 25972c6..3c641cb 100644
--- a/core/src/main/java/brooklyn/entity/basic/BrooklynConfigKeys.java
+++ b/core/src/main/java/brooklyn/entity/basic/BrooklynConfigKeys.java
@@ -143,6 +143,7 @@ public class BrooklynConfigKeys {
      * component is up, but this entity does not care about the dependent 
component's actual config values.
      */
 
+    public static final ConfigKey<Boolean> PROVISION_LATCH = 
newBooleanConfigKey("provision.latch", "Latch for blocking location provision 
until ready");
     public static final ConfigKey<Boolean> START_LATCH = 
newBooleanConfigKey("start.latch", "Latch for blocking start until ready");
     public static final ConfigKey<Boolean> SETUP_LATCH = 
newBooleanConfigKey("setup.latch", "Latch for blocking setup until ready");
     public static final ConfigKey<Boolean> PRE_INSTALL_RESOURCES_LATCH = 
newBooleanConfigKey("resources.preInstall.latch", "Latch for blocking 
pre-install resources until ready");

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/620e4c18/software/base/pom.xml
----------------------------------------------------------------------
diff --git a/software/base/pom.xml b/software/base/pom.xml
index 443b8cd..ba077ce 100644
--- a/software/base/pom.xml
+++ b/software/base/pom.xml
@@ -141,6 +141,13 @@
             <scope>test</scope>
         </dependency>
         <dependency>
+            <groupId>org.apache.brooklyn</groupId>
+            <artifactId>brooklyn-locations-jclouds</artifactId>
+            <version>${project.version}</version>
+            <classifier>tests</classifier>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
             <groupId>mx4j</groupId>
             <artifactId>mx4j-tools</artifactId>
             <scope>test</scope>

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/620e4c18/software/base/src/main/java/brooklyn/entity/software/MachineLifecycleEffectorTasks.java
----------------------------------------------------------------------
diff --git 
a/software/base/src/main/java/brooklyn/entity/software/MachineLifecycleEffectorTasks.java
 
b/software/base/src/main/java/brooklyn/entity/software/MachineLifecycleEffectorTasks.java
index 9c929bb..2ba42f7 100644
--- 
a/software/base/src/main/java/brooklyn/entity/software/MachineLifecycleEffectorTasks.java
+++ 
b/software/base/src/main/java/brooklyn/entity/software/MachineLifecycleEffectorTasks.java
@@ -25,7 +25,6 @@ import java.util.Collections;
 import java.util.List;
 import java.util.Map;
 import java.util.concurrent.Callable;
-
 import javax.annotation.Nullable;
 
 import org.slf4j.Logger;
@@ -275,6 +274,8 @@ public abstract class MachineLifecycleEffectorTasks {
         return 
DynamicTasks.queue(Tasks.<MachineLocation>builder().name("provisioning 
("+location.getDisplayName()+")").body(
                 new Callable<MachineLocation>() {
                     public MachineLocation call() throws Exception {
+                        // Blocks if a latch was configured.
+                        entity().getConfig(BrooklynConfigKeys.PROVISION_LATCH);
                         final Map<String,Object> flags = 
obtainProvisioningFlags(location);
                         if (!(location instanceof 
LocalhostMachineProvisioningLocation))
                             log.info("Starting {}, obtaining a new location 
instance in {} with ports {}", new Object[] {entity(), location, 
flags.get("inboundPorts")});

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/620e4c18/software/base/src/test/java/brooklyn/entity/software/MachineLifecycleEffectorTasksTest.java
----------------------------------------------------------------------
diff --git 
a/software/base/src/test/java/brooklyn/entity/software/MachineLifecycleEffectorTasksTest.java
 
b/software/base/src/test/java/brooklyn/entity/software/MachineLifecycleEffectorTasksTest.java
index 2e73ca7..24fa657 100644
--- 
a/software/base/src/test/java/brooklyn/entity/software/MachineLifecycleEffectorTasksTest.java
+++ 
b/software/base/src/test/java/brooklyn/entity/software/MachineLifecycleEffectorTasksTest.java
@@ -19,14 +19,41 @@
 package brooklyn.entity.software;
 
 import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertFalse;
+import static org.testng.Assert.assertTrue;
+
+import java.util.List;
 
 import org.testng.annotations.DataProvider;
 import org.testng.annotations.Test;
 
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.Iterables;
+import com.google.common.collect.Lists;
+
+import brooklyn.entity.Entity;
+import brooklyn.entity.basic.BasicEntity;
 import brooklyn.entity.basic.BasicEntityImpl;
+import brooklyn.entity.basic.BrooklynConfigKeys;
+import brooklyn.entity.basic.BrooklynTaskTags;
+import brooklyn.entity.basic.EmptySoftwareProcess;
+import brooklyn.entity.basic.Entities;
+import brooklyn.entity.basic.EntityLocal;
 import brooklyn.entity.basic.Lifecycle;
 import brooklyn.entity.basic.SoftwareProcess;
 import brooklyn.entity.basic.SoftwareProcess.StopSoftwareParameters.StopMode;
+import brooklyn.entity.proxying.EntitySpec;
+import brooklyn.entity.trait.Startable;
+import brooklyn.event.AttributeSensor;
+import brooklyn.event.basic.DependentConfiguration;
+import brooklyn.event.basic.Sensors;
+import brooklyn.location.jclouds.BailOutJcloudsLocation;
+import brooklyn.management.Task;
+import brooklyn.test.Asserts;
+import brooklyn.test.entity.TestApplication;
+import brooklyn.util.task.TaskInternal;
+import brooklyn.util.time.Duration;
 
 public class MachineLifecycleEffectorTasksTest {
     public static boolean canStop(StopMode stopMode, boolean isEntityStopped) {
@@ -54,4 +81,59 @@ public class MachineLifecycleEffectorTasksTest {
         assertEquals(canStop, expected);
     }
 
+    @Test
+    public void testProvisionLatchObeyed() throws Exception {
+
+        AttributeSensor<Boolean> ready = Sensors.newBooleanSensor("readiness");
+
+        TestApplication app = 
TestApplication.Factory.newManagedInstanceForTests();
+        BasicEntity triggerEntity = 
app.createAndManageChild(EntitySpec.create(BasicEntity.class));
+
+        EmptySoftwareProcess entity = 
app.createAndManageChild(EntitySpec.create(EmptySoftwareProcess.class)
+                .configure(BrooklynConfigKeys.PROVISION_LATCH, 
DependentConfiguration.attributeWhenReady(triggerEntity, ready)));
+
+        final Task<Void> task = Entities.invokeEffector(app, app, 
Startable.START, ImmutableMap.of(
+                "locations", 
ImmutableList.of(BailOutJcloudsLocation.newBailOutJcloudsLocation(app.getManagementContext()))));
+
+        assertEffectorBlockingDetailsEventually(entity, "Waiting for config " 
+ BrooklynConfigKeys.PROVISION_LATCH.getName());
+
+        Asserts.succeedsContinually(new Runnable() {
+            @Override
+            public void run() {
+                assertFalse(task.isDone());
+            }
+        });
+        try {
+            ((EntityLocal) triggerEntity).setAttribute(ready, true);
+            task.get(Duration.THIRTY_SECONDS);
+        } catch (Throwable t) {
+            // BailOut location throws but we don't care.
+        } finally {
+            Entities.destroyAll(app.getManagementContext());
+        }
+    }
+
+    private void assertEffectorBlockingDetailsEventually(final Entity entity, 
final String blockingDetailsSnippet) {
+        Asserts.succeedsEventually(new Runnable() {
+            @Override public void run() {
+                Task<?> entityTask = 
Iterables.getOnlyElement(entity.getApplication().getManagementContext().getExecutionManager().getTasksWithAllTags(
+                        ImmutableList.of(BrooklynTaskTags.EFFECTOR_TAG, 
BrooklynTaskTags.tagForContextEntity(entity))));
+                String blockingDetails = getBlockingDetails(entityTask);
+                assertTrue(blockingDetails.contains(blockingDetailsSnippet));
+            }});
+    }
+
+    private String getBlockingDetails(Task<?> task) {
+        List<TaskInternal<?>> taskChain = Lists.newArrayList();
+        TaskInternal<?> taskI = (TaskInternal<?>) task;
+        while (taskI != null) {
+            taskChain.add(taskI);
+            if (taskI.getBlockingDetails() != null) {
+                return taskI.getBlockingDetails();
+            }
+            taskI = (TaskInternal<?>) taskI.getBlockingTask();
+        }
+        throw new IllegalStateException("No blocking details for "+task+" 
(walked task chain "+taskChain+")");
+    }
+
 }

Reply via email to