BYON: machine gets extra conf for duration of use

When calling `byon.obtain(customConfig)`, the returned machine will
have the given custom config. When the machine is released, the
config will be restored to what it was before.

Adds ConfigSupportInternal.removeFromLocalBag(String key)

Adds DoNothingSoftwareProcess, for testing


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

Branch: refs/heads/master
Commit: 3ccd165497f5b448d57a0f1df9ef4863afb5654b
Parents: 9be60ca
Author: Aled Sage <[email protected]>
Authored: Thu Jul 30 23:36:12 2015 +0100
Committer: Aled Sage <[email protected]>
Committed: Fri Jul 31 09:52:39 2015 +0100

----------------------------------------------------------------------
 .../brooklyn/basic/BrooklynObjectInternal.java  |  3 +
 .../brooklyn/entity/basic/AbstractEntity.java   |  5 ++
 .../brooklyn/entity/basic/EntityConfigMap.java  |  5 ++
 .../location/basic/AbstractLocation.java        |  7 +-
 .../FixedListMachineProvisioningLocation.java   | 36 +++++++++++
 .../policy/basic/AbstractEntityAdjunct.java     |  5 ++
 .../brooklyn/policy/basic/ConfigMapImpl.java    | 12 ++--
 .../java/brooklyn/util/config/ConfigBag.java    | 13 ++++
 ...ixedListMachineProvisioningLocationTest.java | 58 ++++++++++++++++-
 .../entity/software/MachineInitTasks.java       |  2 +-
 .../entity/basic/DoNothingSoftwareProcess.java  | 30 +++++++++
 .../basic/DoNothingSoftwareProcessDriver.java   | 67 ++++++++++++++++++++
 .../basic/DoNothingSoftwareProcessImpl.java     | 35 ++++++++++
 .../bind/DoNothingSoftwareProcessDriver.java    |  7 +-
 usage/camp/pom.xml                              |  7 ++
 .../camp/brooklyn/ByonLocationsYamlTest.java    | 36 +++++++++++
 16 files changed, 317 insertions(+), 11 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/3ccd1654/core/src/main/java/brooklyn/basic/BrooklynObjectInternal.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/basic/BrooklynObjectInternal.java 
b/core/src/main/java/brooklyn/basic/BrooklynObjectInternal.java
index 8271b35..81ddc7f 100644
--- a/core/src/main/java/brooklyn/basic/BrooklynObjectInternal.java
+++ b/core/src/main/java/brooklyn/basic/BrooklynObjectInternal.java
@@ -91,6 +91,9 @@ public interface BrooklynObjectInternal extends 
BrooklynObject, Rebindable {
         void addToLocalBag(Map<String, ?> vals);
 
         @Beta
+        void removeFromLocalBag(String key);
+
+        @Beta
         void refreshInheritedConfig();
         
         @Beta

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/3ccd1654/core/src/main/java/brooklyn/entity/basic/AbstractEntity.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/entity/basic/AbstractEntity.java 
b/core/src/main/java/brooklyn/entity/basic/AbstractEntity.java
index 507900a..d636e47 100644
--- a/core/src/main/java/brooklyn/entity/basic/AbstractEntity.java
+++ b/core/src/main/java/brooklyn/entity/basic/AbstractEntity.java
@@ -1044,6 +1044,11 @@ public abstract class AbstractEntity extends 
AbstractBrooklynObject implements E
         }
 
         @Override
+        public void removeFromLocalBag(String key) {
+            configsInternal.removeFromLocalBag(key);
+        }
+
+        @Override
         public void refreshInheritedConfig() {
             if (getParent() != null) {
                 
configsInternal.setInheritedConfig(((EntityInternal)getParent()).getAllConfig(),
 ((EntityInternal)getParent()).config().getBag());

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/3ccd1654/core/src/main/java/brooklyn/entity/basic/EntityConfigMap.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/entity/basic/EntityConfigMap.java 
b/core/src/main/java/brooklyn/entity/basic/EntityConfigMap.java
index f2821d8..95ce3d0 100644
--- a/core/src/main/java/brooklyn/entity/basic/EntityConfigMap.java
+++ b/core/src/main/java/brooklyn/entity/basic/EntityConfigMap.java
@@ -275,6 +275,11 @@ public class EntityConfigMap extends AbstractConfigMapImpl 
{
         ownConfig.putAll(localConfigBag.getAllConfigAsConfigKeyMap());
     }
 
+    public void removeFromLocalBag(String key) {
+        localConfigBag.remove(key);
+        ownConfig.remove(key);
+    }
+
     public void clearInheritedConfig() {
         inheritedConfig.clear();
         inheritedConfigBag.clear();

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/3ccd1654/core/src/main/java/brooklyn/location/basic/AbstractLocation.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/location/basic/AbstractLocation.java 
b/core/src/main/java/brooklyn/location/basic/AbstractLocation.java
index 80aa804..3cd35fa 100644
--- a/core/src/main/java/brooklyn/location/basic/AbstractLocation.java
+++ b/core/src/main/java/brooklyn/location/basic/AbstractLocation.java
@@ -442,7 +442,12 @@ public abstract class AbstractLocation extends 
AbstractBrooklynObject implements
         public void addToLocalBag(Map<String, ?> vals) {
             configBag.putAll(vals);
         }
-        
+
+        @Override
+        public void removeFromLocalBag(String key) {
+            configBag.remove(key);
+        }
+
         @Override
         public void refreshInheritedConfig() {
             // no-op for location

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/3ccd1654/core/src/main/java/brooklyn/location/basic/FixedListMachineProvisioningLocation.java
----------------------------------------------------------------------
diff --git 
a/core/src/main/java/brooklyn/location/basic/FixedListMachineProvisioningLocation.java
 
b/core/src/main/java/brooklyn/location/basic/FixedListMachineProvisioningLocation.java
index 50a2a17..1e2184d 100644
--- 
a/core/src/main/java/brooklyn/location/basic/FixedListMachineProvisioningLocation.java
+++ 
b/core/src/main/java/brooklyn/location/basic/FixedListMachineProvisioningLocation.java
@@ -98,6 +98,9 @@ implements MachineProvisioningLocation<T>, Closeable {
     @SetFromFlag
     protected Set<T> pendingRemoval;
     
+    @SetFromFlag
+    protected Map<T, Map<String, Object>> origConfigs;
+
     public FixedListMachineProvisioningLocation() {
         this(Maps.newLinkedHashMap());
     }
@@ -143,6 +146,7 @@ implements MachineProvisioningLocation<T>, Closeable {
         if (machines == null) machines = Sets.newLinkedHashSet();
         if (inUse == null) inUse = Sets.newLinkedHashSet();
         if (pendingRemoval == null) pendingRemoval = Sets.newLinkedHashSet();
+        if (origConfigs == null) origConfigs = Maps.newLinkedHashMap();
         return super.configure(properties);
     }
     
@@ -271,6 +275,7 @@ implements MachineProvisioningLocation<T>, Closeable {
                 }
             }
             inUse.add(machine);
+            updateMachineConfig(machine, flags);
         }
         
         for (MachineLocationCustomizer customizer : 
getMachineCustomizers(allflags)) {
@@ -290,6 +295,7 @@ implements MachineProvisioningLocation<T>, Closeable {
         synchronized (lock) {
             if (inUse.contains(machine) == false)
                 throw new IllegalStateException("Request to release machine 
"+machine+", but this machine is not currently allocated");
+            restoreMachineConfig(machine);
             inUse.remove(machine);
             
             if (pendingRemoval.contains(machine)) {
@@ -303,6 +309,36 @@ implements MachineProvisioningLocation<T>, Closeable {
         return Maps.<String,Object>newLinkedHashMap();
     }
     
+    protected void updateMachineConfig(T machine, Map<?, ?> flags) {
+        if (origConfigs == null) {
+            // For backwards compatibility, where peristed state did not have 
this.
+            origConfigs = Maps.newLinkedHashMap();
+        }
+        Map<String, Object> strFlags = 
ConfigBag.newInstance(flags).getAllConfig();
+        Map<String, Object> origConfig = 
((ConfigurationSupportInternal)machine.config()).getLocalBag().getAllConfig();
+        origConfigs.put(machine, origConfig);
+        requestPersist();
+        
+        
((ConfigurationSupportInternal)machine.config()).addToLocalBag(strFlags);
+    }
+    
+    protected void restoreMachineConfig(MachineLocation machine) {
+        if (origConfigs == null) {
+            // For backwards compatibility, where peristed state did not have 
this.
+            origConfigs = Maps.newLinkedHashMap();
+        }
+        Map<String, Object> origConfig = origConfigs.remove(machine);
+        if (origConfig == null) return;
+        requestPersist();
+        
+        Set<String> currentKeys = 
((ConfigurationSupportInternal)machine.config()).getLocalBag().getAllConfig().keySet();
+        Set<String> newKeys = Sets.difference(currentKeys, 
origConfig.entrySet());
+        for (String key : newKeys) {
+            
((ConfigurationSupportInternal)machine.config()).removeFromLocalBag(key);
+        }
+        
((ConfigurationSupportInternal)machine.config()).addToLocalBag(origConfig);
+    }
+    
     @SuppressWarnings("unchecked")
     private <K> K getConfigPreferringOverridden(ConfigKey<K> key, Map<?,?> 
overrides) {
         K result = (K) overrides.get(key);

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/3ccd1654/core/src/main/java/brooklyn/policy/basic/AbstractEntityAdjunct.java
----------------------------------------------------------------------
diff --git 
a/core/src/main/java/brooklyn/policy/basic/AbstractEntityAdjunct.java 
b/core/src/main/java/brooklyn/policy/basic/AbstractEntityAdjunct.java
index b14fd3e..1b91ce9 100644
--- a/core/src/main/java/brooklyn/policy/basic/AbstractEntityAdjunct.java
+++ b/core/src/main/java/brooklyn/policy/basic/AbstractEntityAdjunct.java
@@ -282,6 +282,11 @@ public abstract class AbstractEntityAdjunct extends 
AbstractBrooklynObject imple
         }
         
         @Override
+        public void removeFromLocalBag(String key) {
+            configsInternal.removeFromLocalBag(key);
+        }
+        
+        @Override
         public void refreshInheritedConfig() {
             // no-op for location
         }

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/3ccd1654/core/src/main/java/brooklyn/policy/basic/ConfigMapImpl.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/policy/basic/ConfigMapImpl.java 
b/core/src/main/java/brooklyn/policy/basic/ConfigMapImpl.java
index dc34b17..9f7b958 100644
--- a/core/src/main/java/brooklyn/policy/basic/ConfigMapImpl.java
+++ b/core/src/main/java/brooklyn/policy/basic/ConfigMapImpl.java
@@ -26,6 +26,10 @@ import java.util.Map;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+import com.google.common.base.Preconditions;
+import com.google.common.base.Predicate;
+import com.google.common.collect.Maps;
+
 import brooklyn.config.ConfigKey;
 import brooklyn.config.internal.AbstractConfigMapImpl;
 import brooklyn.entity.basic.ConfigKeys;
@@ -38,10 +42,6 @@ import brooklyn.util.flags.TypeCoercions;
 import brooklyn.util.guava.Maybe;
 import brooklyn.util.internal.ConfigKeySelfExtracting;
 
-import com.google.common.base.Preconditions;
-import com.google.common.base.Predicate;
-import com.google.common.collect.Maps;
-
 public class ConfigMapImpl extends AbstractConfigMapImpl {
 
     private static final Logger LOG = 
LoggerFactory.getLogger(ConfigMapImpl.class);
@@ -119,6 +119,10 @@ public class ConfigMapImpl extends AbstractConfigMapImpl {
         }
     }
 
+    public void removeFromLocalBag(String key) {
+        ownConfig.remove(key);
+    }
+
     @Override
     public ConfigMapImpl submap(Predicate<ConfigKey<?>> filter) {
         ConfigMapImpl m = new ConfigMapImpl(adjunct);

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/3ccd1654/core/src/main/java/brooklyn/util/config/ConfigBag.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/util/config/ConfigBag.java 
b/core/src/main/java/brooklyn/util/config/ConfigBag.java
index 606e2fc..2f17748 100644
--- a/core/src/main/java/brooklyn/util/config/ConfigBag.java
+++ b/core/src/main/java/brooklyn/util/config/ConfigBag.java
@@ -354,6 +354,19 @@ public class ConfigBag {
         return getStringKeyMaybe(key, true);
     }
 
+    /** gets a {@link Maybe}-wrapped value from a key, inferring the type of 
that key (e.g. {@link ConfigKey} or {@link String}) */
+    @Beta
+    public Maybe<Object> getObjKeyMaybe(Object key) {
+        if (key instanceof HasConfigKey<?>) key = 
((HasConfigKey<?>)key).getConfigKey();
+        if (key instanceof ConfigKey<?>) key = ((ConfigKey<?>)key).getName();
+        if (key instanceof String) {
+            return getStringKeyMaybe((String)key, true);
+        } else {
+            logInvalidKey(key);
+            return Maybe.absent();
+        }
+    }
+
     /** like get, but without marking it as used */
     public <T> T peek(ConfigKey<T> key) {
         return get(key, false);

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/3ccd1654/core/src/test/java/brooklyn/location/basic/FixedListMachineProvisioningLocationTest.java
----------------------------------------------------------------------
diff --git 
a/core/src/test/java/brooklyn/location/basic/FixedListMachineProvisioningLocationTest.java
 
b/core/src/test/java/brooklyn/location/basic/FixedListMachineProvisioningLocationTest.java
index 78a61a9..bf33ea7 100644
--- 
a/core/src/test/java/brooklyn/location/basic/FixedListMachineProvisioningLocationTest.java
+++ 
b/core/src/test/java/brooklyn/location/basic/FixedListMachineProvisioningLocationTest.java
@@ -19,6 +19,7 @@
 package brooklyn.location.basic;
 
 import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertFalse;
 import static org.testng.Assert.fail;
 
 import java.net.Inet4Address;
@@ -41,6 +42,8 @@ import com.google.common.collect.ImmutableSet;
 import com.google.common.collect.Iterables;
 import com.google.common.collect.Lists;
 
+import brooklyn.config.ConfigKey;
+import brooklyn.entity.basic.ConfigKeys;
 import brooklyn.entity.basic.Entities;
 import brooklyn.location.LocationSpec;
 import brooklyn.location.MachineLocation;
@@ -498,8 +501,61 @@ public class FixedListMachineProvisioningLocationTest {
         SshMachineLocation obtained = 
provisioner.obtain(ImmutableMap.of(FixedListMachineProvisioningLocation.MACHINE_LOCATION_CUSTOMIZERS,
 ImmutableList.of(customizer)));
         assertEquals(Iterables.getOnlyElement(customizer.calls), new 
Call("customize", ImmutableList.of(obtained)));
         
-        // TODO Does not call preRelease, because customizer is not config on 
provisioner, and is not config on machine
         provisioner.release(obtained);
+        assertEquals(customizer.calls.size(), 2);
+        assertEquals(customizer.calls.get(1), new Call("preRelease", 
ImmutableList.of(obtained)));
+    }
+
+    @Test
+    public void testMachineGivenCustomFlagForDurationOfUsage() throws 
Exception {
+        boolean origContains = 
machine.config().getBag().getAllConfig().containsKey("mykey");
+        SshMachineLocation obtained = 
provisioner.obtain(ImmutableMap.of("mykey", "myNewVal"));
+        Object obtainedVal = 
obtained.config().getBag().getAllConfig().get("mykey");
+        provisioner.release(obtained);
+        boolean releasedContains = 
obtained.config().getBag().getAllConfig().containsKey("mykey");
+        
+        assertEquals(obtained, machine);
+        assertFalse(origContains);
+        assertEquals(obtainedVal, "myNewVal");
+        assertFalse(releasedContains);
+    }
+    
+    @Test
+    public void testMachineConfigRestoredToDefaultsOnRelease() throws 
Exception {
+        ConfigKey<String> mykey = ConfigKeys.newStringConfigKey("mykey");
+        
+        boolean origContains = 
machine.config().getBag().getAllConfig().containsKey("mykey");
+        SshMachineLocation obtained = provisioner.obtain();
+        obtained.config().set(mykey, "myNewVal");
+        Object obtainedVal = 
obtained.config().getBag().getAllConfig().get("mykey");
+        
+        provisioner.release(obtained);
+        boolean releasedContains = 
machine.config().getBag().getAllConfig().containsKey("mykey");
+        releasedContains |= (machine.config().get(mykey) != null);
+        
+        assertEquals(obtained, machine);
+        assertFalse(origContains);
+        assertEquals(obtainedVal, "myNewVal");
+        assertFalse(releasedContains);
+    }
+    
+    @Test
+    public void testMachineGivenOverriddenFlagForDurationOfUsage() throws 
Exception {
+        SshMachineLocation machine2 = new SshMachineLocation(
+                MutableMap.of("address", 
Inet4Address.getByName("192.168.144.200"), "mykey", "myval"));
+        provisioner2 = new 
FixedListMachineProvisioningLocation<SshMachineLocation>(
+                MutableMap.of("machines", MutableList.of(machine2)));
+
+        Object origVal = 
machine2.config().getBag().getAllConfig().get("mykey");
+        SshMachineLocation obtained = 
provisioner2.obtain(ImmutableMap.of("mykey", "myNewVal"));
+        Object obtainedVal = 
obtained.config().getBag().getAllConfig().get("mykey");
+        provisioner2.release(obtained);
+        Object releasedVal = 
obtained.config().getBag().getAllConfig().get("mykey");
+        
+        assertEquals(obtained, machine2);
+        assertEquals(origVal, "myval");
+        assertEquals(obtainedVal, "myNewVal");
+        assertEquals(releasedVal, "myval");
     }
 
     private static <T> List<T> randomized(Iterable<T> list) {

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/3ccd1654/software/base/src/main/java/brooklyn/entity/software/MachineInitTasks.java
----------------------------------------------------------------------
diff --git 
a/software/base/src/main/java/brooklyn/entity/software/MachineInitTasks.java 
b/software/base/src/main/java/brooklyn/entity/software/MachineInitTasks.java
index dfcb61d..57a5926 100644
--- a/software/base/src/main/java/brooklyn/entity/software/MachineInitTasks.java
+++ b/software/base/src/main/java/brooklyn/entity/software/MachineInitTasks.java
@@ -85,7 +85,7 @@ public class MachineInitTasks {
      * See docs in {@link BashCommands#dontRequireTtyForSudo()}
      */
     public Task<Boolean> dontRequireTtyForSudoAsync(final SshMachineLocation 
machine) {
-        return SshTasks.dontRequireTtyForSudo(machine, 
true).newTask().asTask();
+        return DynamicTasks.queue(SshTasks.dontRequireTtyForSudo(machine, 
true).newTask().asTask());
     }
 
     protected void openIptablesImpl(Iterable<Integer> inboundPorts, 
SshMachineLocation machine) {

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/3ccd1654/software/base/src/test/java/brooklyn/entity/basic/DoNothingSoftwareProcess.java
----------------------------------------------------------------------
diff --git 
a/software/base/src/test/java/brooklyn/entity/basic/DoNothingSoftwareProcess.java
 
b/software/base/src/test/java/brooklyn/entity/basic/DoNothingSoftwareProcess.java
new file mode 100644
index 0000000..19fc1cc
--- /dev/null
+++ 
b/software/base/src/test/java/brooklyn/entity/basic/DoNothingSoftwareProcess.java
@@ -0,0 +1,30 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package brooklyn.entity.basic;
+
+import brooklyn.config.ConfigKey;
+import brooklyn.entity.proxying.ImplementedBy;
+
+@ImplementedBy(DoNothingSoftwareProcessImpl.class)
+public interface DoNothingSoftwareProcess extends SoftwareProcess {
+    
+    public static final ConfigKey<Boolean> SKIP_ON_BOX_BASE_DIR_RESOLUTION = 
ConfigKeys.newConfigKeyWithDefault(
+            BrooklynConfigKeys.SKIP_ON_BOX_BASE_DIR_RESOLUTION,
+            true);
+}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/3ccd1654/software/base/src/test/java/brooklyn/entity/basic/DoNothingSoftwareProcessDriver.java
----------------------------------------------------------------------
diff --git 
a/software/base/src/test/java/brooklyn/entity/basic/DoNothingSoftwareProcessDriver.java
 
b/software/base/src/test/java/brooklyn/entity/basic/DoNothingSoftwareProcessDriver.java
new file mode 100644
index 0000000..aadb898
--- /dev/null
+++ 
b/software/base/src/test/java/brooklyn/entity/basic/DoNothingSoftwareProcessDriver.java
@@ -0,0 +1,67 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package brooklyn.entity.basic;
+
+import brooklyn.location.basic.SshMachineLocation;
+
+/**
+ * Implements methods in {@link 
brooklyn.entity.basic.AbstractSoftwareProcessSshDriver}
+ * such that no actions are performed.
+ * <p>
+ * {@link #isRunning()} returns true.
+ */
+public class DoNothingSoftwareProcessDriver extends 
AbstractSoftwareProcessSshDriver {
+
+    public DoNothingSoftwareProcessDriver(EntityLocal entity, 
SshMachineLocation machine) {
+        super(entity, machine);
+    }
+
+    @Override
+    public boolean isRunning() {
+        return true;
+    }
+
+    @Override
+    public void copyPreInstallResources() {
+    }
+
+    @Override
+    public void copyInstallResources() {
+    }
+
+    @Override
+    public void copyRuntimeResources() {
+    }
+
+    @Override
+    public void install() {
+    }
+
+    @Override
+    public void customize() {
+    }
+
+    @Override
+    public void launch() {
+    }
+
+    @Override
+    public void stop() {
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/3ccd1654/software/base/src/test/java/brooklyn/entity/basic/DoNothingSoftwareProcessImpl.java
----------------------------------------------------------------------
diff --git 
a/software/base/src/test/java/brooklyn/entity/basic/DoNothingSoftwareProcessImpl.java
 
b/software/base/src/test/java/brooklyn/entity/basic/DoNothingSoftwareProcessImpl.java
new file mode 100644
index 0000000..17cc9fe
--- /dev/null
+++ 
b/software/base/src/test/java/brooklyn/entity/basic/DoNothingSoftwareProcessImpl.java
@@ -0,0 +1,35 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package brooklyn.entity.basic;
+
+public class DoNothingSoftwareProcessImpl extends SoftwareProcessImpl 
implements DoNothingSoftwareProcess {
+
+    @Override
+    public Class getDriverInterface() {
+        return DoNothingSoftwareProcessDriver.class;
+    }
+    
+    @Override
+    protected void connectSensors() {
+        super.connectSensors();
+        if (getAttribute(SERVICE_STATE_ACTUAL) == Lifecycle.STARTING) {
+            setAttribute(SERVICE_UP, true);
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/3ccd1654/software/network/src/test/java/brooklyn/entity/network/bind/DoNothingSoftwareProcessDriver.java
----------------------------------------------------------------------
diff --git 
a/software/network/src/test/java/brooklyn/entity/network/bind/DoNothingSoftwareProcessDriver.java
 
b/software/network/src/test/java/brooklyn/entity/network/bind/DoNothingSoftwareProcessDriver.java
index c49e66b..df7953d 100644
--- 
a/software/network/src/test/java/brooklyn/entity/network/bind/DoNothingSoftwareProcessDriver.java
+++ 
b/software/network/src/test/java/brooklyn/entity/network/bind/DoNothingSoftwareProcessDriver.java
@@ -38,10 +38,6 @@ public class DoNothingSoftwareProcessDriver extends 
AbstractSoftwareProcessSshDr
     }
 
     @Override
-    public void stop() {
-    }
-
-    @Override
     public void install() {
     }
 
@@ -53,4 +49,7 @@ public class DoNothingSoftwareProcessDriver extends 
AbstractSoftwareProcessSshDr
     public void launch() {
     }
 
+    @Override
+    public void stop() {
+    }
 }

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/3ccd1654/usage/camp/pom.xml
----------------------------------------------------------------------
diff --git a/usage/camp/pom.xml b/usage/camp/pom.xml
index 5b6c8fc..9a643e1 100644
--- a/usage/camp/pom.xml
+++ b/usage/camp/pom.xml
@@ -120,6 +120,13 @@
         </dependency>
         <dependency>
             <groupId>org.apache.brooklyn</groupId>
+            <artifactId>brooklyn-software-base</artifactId>
+            <version>${project.version}</version>
+            <classifier>tests</classifier>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.brooklyn</groupId>
             <artifactId>brooklyn-software-webapp</artifactId>
             <version>${project.version}</version>
             <scope>test</scope>

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/3ccd1654/usage/camp/src/test/java/io/brooklyn/camp/brooklyn/ByonLocationsYamlTest.java
----------------------------------------------------------------------
diff --git 
a/usage/camp/src/test/java/io/brooklyn/camp/brooklyn/ByonLocationsYamlTest.java 
b/usage/camp/src/test/java/io/brooklyn/camp/brooklyn/ByonLocationsYamlTest.java
index 3ddc5ad..eaf3884 100644
--- 
a/usage/camp/src/test/java/io/brooklyn/camp/brooklyn/ByonLocationsYamlTest.java
+++ 
b/usage/camp/src/test/java/io/brooklyn/camp/brooklyn/ByonLocationsYamlTest.java
@@ -31,6 +31,7 @@ import org.testng.annotations.Test;
 
 import com.google.api.client.repackaged.com.google.common.base.Joiner;
 import com.google.common.base.Predicates;
+import com.google.common.collect.ImmutableList;
 import com.google.common.collect.ImmutableMap;
 import com.google.common.collect.ImmutableSet;
 import com.google.common.collect.Iterables;
@@ -38,12 +39,17 @@ import com.google.common.net.HostAndPort;
 
 import brooklyn.entity.Entity;
 import brooklyn.entity.basic.ConfigKeys;
+import brooklyn.entity.basic.DoNothingSoftwareProcess;
+import brooklyn.entity.basic.Entities;
 import brooklyn.location.MachineLocation;
 import brooklyn.location.access.PortForwardManager;
 import brooklyn.location.basic.FixedListMachineProvisioningLocation;
 import brooklyn.location.basic.LocationPredicates;
+import brooklyn.location.basic.Machines;
 import brooklyn.location.basic.SshMachineLocation;
 import brooklyn.location.basic.WinRmMachineLocation;
+import brooklyn.location.cloud.CloudLocationConfig;
+import brooklyn.test.Asserts;
 import brooklyn.util.net.UserAndHostAndPort;
 
 public class ByonLocationsYamlTest extends AbstractYamlTest {
@@ -218,6 +224,36 @@ public class ByonLocationsYamlTest extends 
AbstractYamlTest {
         assertNull(pfm.lookup(machine2, 12345));
     }
 
+    @Test
+    @SuppressWarnings("unchecked")
+    public void testPassesInboundPortsToMachineAndRemovesOnceMachineReleased() 
throws Exception {
+        String yaml = Joiner.on("\n").join(
+                "location:",
+                "  byon:",
+                "    hosts:",
+                "    - ssh: 1.1.1.1:22",
+                "      password: mypassword",
+                "      user: myuser",
+                "services:",
+                "- type: brooklyn.entity.basic.DoNothingSoftwareProcess",
+                "  brooklyn.config:",
+                "    requiredOpenLoginPorts: [22, 1024]");
+
+        Entity app = createStartWaitAndLogApplication(new StringReader(yaml));
+        DoNothingSoftwareProcess entity = (DoNothingSoftwareProcess) 
Iterables.find(Entities.descendants(app), 
Predicates.instanceOf(DoNothingSoftwareProcess.class));
+        FixedListMachineProvisioningLocation<MachineLocation> loc = 
(FixedListMachineProvisioningLocation<MachineLocation>) 
Iterables.get(app.getLocations(), 0);
+        
+        // Machine should have been given the inbound-ports
+        SshMachineLocation machine = 
Machines.findUniqueSshMachineLocation(entity.getLocations()).get();
+        
Asserts.assertEqualsIgnoringOrder((Iterable<?>)machine.config().get(CloudLocationConfig.INBOUND_PORTS),
 ImmutableList.of(22, 1024));
+        
+        // Stop the entity; should release the machine
+        entity.stop();
+        MachineLocation availableMachine = 
Iterables.getOnlyElement(loc.getAvailable());
+        assertEquals(availableMachine, machine);
+        assertNull(machine.config().get(CloudLocationConfig.INBOUND_PORTS));
+    }
+
     private void assertMachine(SshMachineLocation machine, UserAndHostAndPort 
conn, Map<String, ?> config) {
         assertEquals(machine.getAddress().getHostAddress(), 
conn.getHostAndPort().getHostText());
         assertEquals(machine.getPort(), conn.getHostAndPort().getPort());

Reply via email to