http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a1ad34d7/core/src/test/java/org/apache/brooklyn/location/core/AggregatingMachineProvisioningLocationTest.java ---------------------------------------------------------------------- diff --git a/core/src/test/java/org/apache/brooklyn/location/core/AggregatingMachineProvisioningLocationTest.java b/core/src/test/java/org/apache/brooklyn/location/core/AggregatingMachineProvisioningLocationTest.java new file mode 100644 index 0000000..be85699 --- /dev/null +++ b/core/src/test/java/org/apache/brooklyn/location/core/AggregatingMachineProvisioningLocationTest.java @@ -0,0 +1,117 @@ +/* + * 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 org.apache.brooklyn.location.core; + +import static org.testng.Assert.assertEquals; +import static org.testng.Assert.fail; + +import java.util.Map; + +import org.apache.brooklyn.api.location.Location; +import org.apache.brooklyn.api.location.LocationSpec; +import org.apache.brooklyn.api.location.MachineProvisioningLocation; +import org.apache.brooklyn.api.location.NoMachinesAvailableException; +import org.apache.brooklyn.core.mgmt.internal.LocalManagementContext; +import org.apache.brooklyn.core.test.entity.LocalManagementContextForTests; +import org.apache.brooklyn.entity.core.Entities; +import org.testng.annotations.AfterMethod; +import org.testng.annotations.BeforeMethod; +import org.testng.annotations.Test; +import org.apache.brooklyn.location.byon.FixedListMachineProvisioningLocation; +import org.apache.brooklyn.location.core.AggregatingMachineProvisioningLocation; +import org.apache.brooklyn.location.localhost.LocalhostMachineProvisioningLocation.LocalhostMachine; + +import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableMap; + +public class AggregatingMachineProvisioningLocationTest { + + + private LocalManagementContext managementContext; + private AggregatingMachineProvisioningLocation<LocalhostMachine> aggregator; + private LocalhostMachine machine1a; + private LocalhostMachine machine1b; + private LocalhostMachine machine2a; + private LocalhostMachine machine2b; + private MachineProvisioningLocation<LocalhostMachine> provisioner1; + private MachineProvisioningLocation<LocalhostMachine> provisioner2; + + @BeforeMethod(alwaysRun=true) + @SuppressWarnings("unchecked") + public void setUp() { + managementContext = new LocalManagementContextForTests(); + machine1a = newLocation(LocalhostMachine.class, "1a"); + machine1b = newLocation(LocalhostMachine.class, "1b"); + machine2a = newLocation(LocalhostMachine.class, "2a"); + machine2b = newLocation(LocalhostMachine.class, "2b"); + provisioner1 = newLocation(FixedListMachineProvisioningLocation.class, ImmutableMap.of("machines", ImmutableList.of(machine1a, machine1b))); + provisioner2 = newLocation(FixedListMachineProvisioningLocation.class, ImmutableMap.of("machines", ImmutableList.of(machine2a, machine2b))); + } + + @AfterMethod(alwaysRun=true) + public void tearDown() { + if (managementContext != null) Entities.destroyAll(managementContext); + } + + @Test + @SuppressWarnings("unchecked") + public void testObtainAndRelease() throws Exception { + aggregator = newLocation(AggregatingMachineProvisioningLocation.class, ImmutableMap.of("provisioners", ImmutableList.of(provisioner1, provisioner2))); + assertEquals(aggregator.obtain(), machine1a); + assertEquals(aggregator.obtain(), machine2a); + assertEquals(aggregator.obtain(), machine1b); + assertEquals(aggregator.obtain(), machine2b); + + try { + aggregator.obtain(); + fail(); + } catch (NoMachinesAvailableException e) { + // success + } + + aggregator.release(machine2b); + assertEquals(aggregator.obtain(), machine2b); + } + + @Test + @SuppressWarnings("unchecked") + public void testReleaseWhenNotHeldThrows() throws Exception { + aggregator = newLocation(AggregatingMachineProvisioningLocation.class, ImmutableMap.of("provisioners", ImmutableList.of(provisioner1, provisioner2))); + try { + aggregator.release(machine1a); + fail(); + } catch (IllegalStateException e) { + if (!e.toString().contains("machine is not currently allocated")) throw e; + } + } + + private <T extends Location> T newLocation(Class<T> clazz, String displayName) { + return newLocation(clazz, displayName, ImmutableMap.of()); + } + + private <T extends Location> T newLocation(Class<T> clazz, Map<?,?> config) { + return newLocation(clazz, "mydisplayname", config); + } + + private <T extends Location> T newLocation(Class<T> clazz, String displayName, Map<?,?> config) { + return managementContext.getLocationManager().createLocation(LocationSpec.create(clazz) + .displayName(displayName) + .configure(config)); + } +}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a1ad34d7/core/src/test/java/org/apache/brooklyn/location/core/LegacyAbstractLocationTest.java ---------------------------------------------------------------------- diff --git a/core/src/test/java/org/apache/brooklyn/location/core/LegacyAbstractLocationTest.java b/core/src/test/java/org/apache/brooklyn/location/core/LegacyAbstractLocationTest.java new file mode 100644 index 0000000..d5d5ae7 --- /dev/null +++ b/core/src/test/java/org/apache/brooklyn/location/core/LegacyAbstractLocationTest.java @@ -0,0 +1,151 @@ +/* + * 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 org.apache.brooklyn.location.core; + +import static org.testng.Assert.assertEquals; +import static org.testng.Assert.assertFalse; +import static org.testng.Assert.assertNotEquals; +import static org.testng.Assert.assertTrue; + +import java.util.Collections; +import java.util.Map; + +import org.apache.brooklyn.location.core.AbstractLocation; +import org.apache.brooklyn.util.collections.MutableMap; +import org.apache.brooklyn.util.core.flags.SetFromFlag; +import org.testng.annotations.AfterMethod; +import org.testng.annotations.Test; + +import com.google.common.collect.ImmutableList; + +public class LegacyAbstractLocationTest { + + private static class ConcreteLocation extends AbstractLocation { + @SetFromFlag(defaultVal="mydefault") + String myfield; + + public ConcreteLocation() { + super(); + } + + public ConcreteLocation(Map properties) { + super(properties); + } + } + + @AfterMethod(alwaysRun = true) + public void tearDown(){ + // nothing to tear down; did not create a management context + } + + @Test + public void testEquals() { + AbstractLocation l1 = new ConcreteLocation(MutableMap.of("id", "1", "name", "bob")); + AbstractLocation l2 = new ConcreteLocation(MutableMap.of("id", "1", "name", "frank")); + AbstractLocation l3 = new ConcreteLocation(MutableMap.of("id", "2", "name", "frank")); + assertEquals(l1, l2); + assertNotEquals(l2, l3); + } + + @Test + public void nullNameAndParentLocationIsAcceptable() { + AbstractLocation location = new ConcreteLocation(MutableMap.of("name", null, "parentLocation", null)); + assertEquals(location.getDisplayName(), null); + assertEquals(location.getParent(), null); + } + + @Test + public void testSettingParentLocation() { + AbstractLocation location = new ConcreteLocation(); + AbstractLocation locationSub = new ConcreteLocation(); + locationSub.setParent(location); + + assertEquals(ImmutableList.copyOf(location.getChildren()), ImmutableList.of(locationSub)); + assertEquals(locationSub.getParent(), location); + } + + @Test + public void testClearingParentLocation() { + AbstractLocation location = new ConcreteLocation(); + AbstractLocation locationSub = new ConcreteLocation(); + locationSub.setParent(location); + + locationSub.setParent(null); + assertEquals(ImmutableList.copyOf(location.getChildren()), Collections.emptyList()); + assertEquals(locationSub.getParent(), null); + } + + @Test + public void testContainsLocation() { + AbstractLocation location = new ConcreteLocation(); + AbstractLocation locationSub = new ConcreteLocation(); + locationSub.setParent(location); + + assertTrue(location.containsLocation(location)); + assertTrue(location.containsLocation(locationSub)); + assertFalse(locationSub.containsLocation(location)); + } + + + @Test + public void queryingNameReturnsNameGivenInConstructor() { + String name = "Outer Mongolia"; + AbstractLocation location = new ConcreteLocation(MutableMap.of("name", "Outer Mongolia")); + assertEquals(location.getDisplayName(), name);; + } + + @Test + public void constructorParentLocationReturnsExpectedLocation() { + AbstractLocation parent = new ConcreteLocation(MutableMap.of("name", "Middle Earth")); + AbstractLocation child = new ConcreteLocation(MutableMap.of("name", "The Shire", "parentLocation", parent)); + assertEquals(child.getParent(), parent); + assertEquals(ImmutableList.copyOf(parent.getChildren()), ImmutableList.of(child)); + } + + @Test + public void setParentLocationReturnsExpectedLocation() { + AbstractLocation parent = new ConcreteLocation(MutableMap.of("name", "Middle Earth")); + AbstractLocation child = new ConcreteLocation(MutableMap.of("name", "The Shire")); + child.setParent(parent); + assertEquals(child.getParent(), parent); + assertEquals(ImmutableList.copyOf(parent.getChildren()), ImmutableList.of(child)); + } + + @Test + public void testAddChildToParentLocationReturnsExpectedLocation() { + AbstractLocation parent = new ConcreteLocation(MutableMap.of("id", "1")); + AbstractLocation child = new ConcreteLocation(MutableMap.of("id", "2")); + parent.addChild(child); + assertEquals(child.getParent(), parent); + assertEquals(ImmutableList.copyOf(parent.getChildren()), ImmutableList.of(child)); + } + + @Test + public void testFieldSetFromFlag() { + ConcreteLocation loc = new ConcreteLocation(MutableMap.of("myfield", "myval")); + assertEquals(loc.myfield, "myval"); + } + + @Test + public void testFieldSetFromFlagUsesDefault() { + ConcreteLocation loc = new ConcreteLocation(); + assertEquals(loc.myfield, "mydefault"); + } + +} http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a1ad34d7/core/src/test/java/org/apache/brooklyn/location/core/LocationConfigTest.java ---------------------------------------------------------------------- diff --git a/core/src/test/java/org/apache/brooklyn/location/core/LocationConfigTest.java b/core/src/test/java/org/apache/brooklyn/location/core/LocationConfigTest.java new file mode 100644 index 0000000..3a953f7 --- /dev/null +++ b/core/src/test/java/org/apache/brooklyn/location/core/LocationConfigTest.java @@ -0,0 +1,204 @@ +/* + * 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 org.apache.brooklyn.location.core; + +import static org.testng.Assert.assertEquals; + +import org.apache.brooklyn.api.location.LocationSpec; +import org.apache.brooklyn.api.mgmt.ManagementContext; +import org.apache.brooklyn.config.ConfigKey; +import org.apache.brooklyn.core.config.ConfigKeys; +import org.apache.brooklyn.core.test.entity.LocalManagementContextForTests; +import org.apache.brooklyn.entity.core.Entities; +import org.apache.brooklyn.location.core.AbstractLocation; +import org.apache.brooklyn.location.core.internal.LocationInternal; +import org.apache.brooklyn.util.core.flags.SetFromFlag; +import org.testng.Assert; +import org.testng.annotations.AfterMethod; +import org.testng.annotations.BeforeMethod; +import org.testng.annotations.Test; + +import com.google.common.collect.ImmutableMap; + +public class LocationConfigTest { + + // TODO Duplication of LocationConfigTest, but with locations instead of entities + + private ManagementContext managementContext; + + @BeforeMethod(alwaysRun=true) + public void setUp() throws Exception { + managementContext = LocalManagementContextForTests.newInstance(); + } + + @AfterMethod(alwaysRun=true) + public void tearDown() { + if (managementContext != null) Entities.destroyAll(managementContext); + } + + @Test + public void testConfigBagContainsMatchesForConfigKeyName() throws Exception { + LocationInternal loc = managementContext.getLocationManager().createLocation(LocationSpec.create(MyLocation.class) + .configure("mylocation.myconfig", "myval1") + .configure("mylocation.myconfigwithflagname", "myval2")); + + assertEquals(loc.config().getBag().getAllConfig(), ImmutableMap.of("mylocation.myconfig", "myval1", "mylocation.myconfigwithflagname", "myval2")); + assertEquals(loc.config().getLocalBag().getAllConfig(), ImmutableMap.of("mylocation.myconfig", "myval1", "mylocation.myconfigwithflagname", "myval2")); + Assert.assertEquals(loc.getAllConfig(true), ImmutableMap.of("mylocation.myconfig", "myval1", "mylocation.myconfigwithflagname", "myval2")); + Assert.assertEquals(loc.getAllConfig(false), ImmutableMap.of("mylocation.myconfig", "myval1", "mylocation.myconfigwithflagname", "myval2")); + } + + // TODO Note difference compared to Location, where both flag-name + config-key-name are in the ConfigBag + @Test + public void testConfigBagContainsMatchesForFlagName() throws Exception { + // Prefers flag-name, over config-key's name + LocationInternal loc = managementContext.getLocationManager().createLocation(LocationSpec.create(MyLocation.class) + .configure("myconfigflagname", "myval")); + + assertEquals(loc.config().getBag().getAllConfig(), ImmutableMap.of("mylocation.myconfigwithflagname", "myval", "myconfigflagname", "myval")); + assertEquals(loc.config().getLocalBag().getAllConfig(), ImmutableMap.of("mylocation.myconfigwithflagname", "myval", "myconfigflagname", "myval")); + Assert.assertEquals(loc.getAllConfig(true), ImmutableMap.of("mylocation.myconfigwithflagname", "myval", "myconfigflagname", "myval")); + Assert.assertEquals(loc.getAllConfig(false), ImmutableMap.of("mylocation.myconfigwithflagname", "myval", "myconfigflagname", "myval")); + } + + @Test + public void testConfigBagContainsUnmatched() throws Exception { + LocationInternal loc = managementContext.getLocationManager().createLocation(LocationSpec.create(MyLocation.class) + .configure("notThere", "notThereVal")); + + assertEquals(loc.config().getBag().getAllConfig(), ImmutableMap.of("notThere", "notThereVal")); + assertEquals(loc.config().getLocalBag().getAllConfig(), ImmutableMap.of("notThere", "notThereVal")); + Assert.assertEquals(loc.getAllConfig(true), ImmutableMap.of("notThere", "notThereVal")); + Assert.assertEquals(loc.getAllConfig(false), ImmutableMap.of("notThere", "notThereVal")); + } + + // TODO Note difference from entity: child's bag contains both the flag-name and the config-key-name + @Test + public void testChildConfigBagInheritsUnmatchedAtParent() throws Exception { + LocationInternal loc = managementContext.getLocationManager().createLocation(LocationSpec.create(MyLocation.class) + .configure("mychildlocation.myconfig", "myval1") + .configure("notThere", "notThereVal")); + + LocationInternal child = managementContext.getLocationManager().createLocation(LocationSpec.create(MyChildLocation.class) + .parent(loc)); + + assertEquals(child.config().getBag().getAllConfig(), ImmutableMap.of("mychildlocation.myconfig", "myval1", "notThere", "notThereVal")); + assertEquals(child.config().getLocalBag().getAllConfig(), ImmutableMap.of()); + Assert.assertEquals(child.getAllConfig(true), ImmutableMap.of("mychildlocation.myconfig", "myval1", "notThere", "notThereVal")); + Assert.assertEquals(child.getAllConfig(false), ImmutableMap.of()); + } + + // TODO Fails for location, but passes for entity; not worth fixing here; locations will soon be entities! + @Test(groups="WIP") + public void testChildConfigBagInheritsFlagNameFromParentSetsOwnConfigKey() throws Exception { + LocationInternal loc = managementContext.getLocationManager().createLocation(LocationSpec.create(MyLocation.class) + .configure("mychildconfigflagname", "myval")); + + LocationInternal child = managementContext.getLocationManager().createLocation(LocationSpec.create(MyChildLocation.class) + .parent(loc)); + + assertEquals(child.config().getBag().getAllConfig(), ImmutableMap.of("mychildlocation.myconfigwithflagname", "myval")); + assertEquals(child.config().getLocalBag().getAllConfig(), ImmutableMap.of()); + Assert.assertEquals(child.getAllConfig(true), ImmutableMap.of("mychildlocation.myconfigwithflagname", "myval")); + Assert.assertEquals(child.getAllConfig(false), ImmutableMap.of()); + } + + @Test + public void testChildInheritsFromParent() throws Exception { + LocationInternal loc = managementContext.getLocationManager().createLocation(LocationSpec.create(MyLocation.class) + .configure("mylocation.myconfig", "myval1")); + + LocationInternal child = managementContext.getLocationManager().createLocation(LocationSpec.create(MyChildLocation.class) + .parent(loc)); + + assertEquals(child.config().getBag().getAllConfig(), ImmutableMap.of("mylocation.myconfig", "myval1")); + assertEquals(child.config().getLocalBag().getAllConfig(), ImmutableMap.of()); + Assert.assertEquals(child.getAllConfig(true), ImmutableMap.of("mylocation.myconfig", "myval1")); + Assert.assertEquals(child.getAllConfig(false), ImmutableMap.of()); + } + + @Test + public void testChildCanOverrideConfigUsingKeyName() throws Exception { + LocationInternal location = managementContext.getLocationManager().createLocation(LocationSpec.create(MyLocation.class) + .configure("mychildlocation.myconfigwithflagname", "myval") + .configure("notThere", "notThereVal")); + + LocationInternal child = managementContext.getLocationManager().createLocation(LocationSpec.create(MyChildLocation.class) + .parent(location) + .configure("mychildlocation.myconfigwithflagname", "overrideMyval") + .configure("notThere", "overrideNotThereVal")); + + assertEquals(child.config().getBag().getAllConfig(), ImmutableMap.of("mychildlocation.myconfigwithflagname", "overrideMyval", "notThere", "overrideNotThereVal")); + assertEquals(child.config().getLocalBag().getAllConfig(), ImmutableMap.of("mychildlocation.myconfigwithflagname", "overrideMyval", "notThere", "overrideNotThereVal")); + Assert.assertEquals(child.getAllConfig(true), ImmutableMap.of("mychildlocation.myconfigwithflagname", "overrideMyval", "notThere", "overrideNotThereVal")); + Assert.assertEquals(child.getAllConfig(false), ImmutableMap.of("mychildlocation.myconfigwithflagname", "overrideMyval", "notThere", "overrideNotThereVal")); + } + + // TODO Note difference compared to Location, where both flag-name + config-key-name are in the ConfigBag + @Test + public void testChildCanOverrideConfigUsingFlagName() throws Exception { + LocationInternal loc = managementContext.getLocationManager().createLocation(LocationSpec.create(MyLocation.class) + .configure("mychildlocation.myconfigwithflagname", "myval")); + + LocationInternal child = managementContext.getLocationManager().createLocation(LocationSpec.create(MyChildLocation.class) + .parent(loc) + .configure("mychildconfigflagname", "overrideMyval")); + + assertEquals(child.config().getBag().getAllConfig(), ImmutableMap.of("mychildlocation.myconfigwithflagname", "overrideMyval", "mychildconfigflagname", "overrideMyval")); + assertEquals(child.config().getLocalBag().getAllConfig(), ImmutableMap.of("mychildlocation.myconfigwithflagname", "overrideMyval", "mychildconfigflagname", "overrideMyval")); + Assert.assertEquals(child.getAllConfig(true), ImmutableMap.of("mychildlocation.myconfigwithflagname", "overrideMyval", "mychildconfigflagname", "overrideMyval")); + Assert.assertEquals(child.getAllConfig(false), ImmutableMap.of("mychildlocation.myconfigwithflagname", "overrideMyval", "mychildconfigflagname", "overrideMyval")); + } + + @Test + public void testLocationCanOverrideConfigDefaultValue() throws Exception { + LocationInternal loc = managementContext.getLocationManager().createLocation(LocationSpec.create(MyLocation.class)); + LocationInternal subloc = managementContext.getLocationManager().createLocation(LocationSpec.create(MySubLocation.class)); + + Assert.assertEquals(loc.getConfig(MyLocation.MY_CONFIG_WITH_DEFAULT), "mydefault"); + Assert.assertEquals(loc.getConfig(ConfigKeys.newStringConfigKey("mylocation.myconfigwithdefault", "", "differentdefault")), "mydefault"); + + Assert.assertEquals(subloc.getConfig(MySubLocation.MY_CONFIG_WITH_DEFAULT), "mysubdefault"); + Assert.assertEquals(subloc.getConfig(MyLocation.MY_CONFIG_WITH_DEFAULT), "mysubdefault"); + } + + @SuppressWarnings("serial") + public static class MyLocation extends AbstractLocation { + public static final ConfigKey<String> MY_CONFIG = ConfigKeys.newStringConfigKey("mylocation.myconfig"); + + @SetFromFlag("myconfigflagname") + public static final ConfigKey<String> MY_CONFIG_WITH_FLAGNAME = ConfigKeys.newStringConfigKey("mylocation.myconfigwithflagname"); + + public static final ConfigKey<String> MY_CONFIG_WITH_DEFAULT = ConfigKeys.newStringConfigKey("mylocation.myconfigwithdefault", "", "mydefault"); + } + + @SuppressWarnings("serial") + public static class MyChildLocation extends AbstractLocation { + public static final ConfigKey<String> MY_CHILD_CONFIG = ConfigKeys.newStringConfigKey("mychildlocation.myconfig"); + + @SetFromFlag("mychildconfigflagname") + public static final ConfigKey<String> MY_CHILD_CONFIG_WITH_FLAGNAME = ConfigKeys.newStringConfigKey("mychildlocation.myconfigwithflagname"); + } + + @SuppressWarnings("serial") + public static class MySubLocation extends MyLocation { + public static final ConfigKey<String> MY_CONFIG_WITH_DEFAULT = ConfigKeys.newConfigKeyWithDefault(MyLocation.MY_CONFIG_WITH_DEFAULT, "mysubdefault"); + } + +} http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a1ad34d7/core/src/test/java/org/apache/brooklyn/location/core/LocationConfigUtilsTest.java ---------------------------------------------------------------------- diff --git a/core/src/test/java/org/apache/brooklyn/location/core/LocationConfigUtilsTest.java b/core/src/test/java/org/apache/brooklyn/location/core/LocationConfigUtilsTest.java new file mode 100644 index 0000000..e22ae12 --- /dev/null +++ b/core/src/test/java/org/apache/brooklyn/location/core/LocationConfigUtilsTest.java @@ -0,0 +1,156 @@ +/* + * 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 org.apache.brooklyn.location.core; + +import static org.testng.Assert.assertEquals; +import static org.testng.Assert.assertTrue; + +import java.io.File; + +import org.apache.brooklyn.location.core.LocationConfigKeys; +import org.apache.brooklyn.location.core.LocationConfigUtils; +import org.apache.brooklyn.util.core.config.ConfigBag; +import org.testng.Assert; +import org.testng.annotations.Test; + +@Test +public class LocationConfigUtilsTest { + + // set these system properties differently if needed to fix your tests + public static final String SSH_PRIVATE_KEY_FILE_WITH_TILDE = System.getProperty("sshPrivateKey", "~/.ssh/id_rsa"); + public static final String SSH_PUBLIC_KEY_FILE_WITH_TILDE = System.getProperty("sshPublicKey", "~/.ssh/id_rsa.pub"); + // these should work as they are on classpath + public static final String SSH_PRIVATE_KEY_FILE_WITH_PASSPHRASE = System.getProperty("sshPrivateKeyWithPassphrase", "/brooklyn/util/crypto/sample_rsa_passphrase.pem"); + public static final String SSH_PRIVATE_KEY_FILE = System.getProperty("sshPrivateKeySample", "/org/apache/brooklyn/location/basic/sample_id_rsa"); + public static final String SSH_PUBLIC_KEY_FILE = System.getProperty("sshPublicKeySample", "/org/apache/brooklyn/location/basic/sample_id_rsa.pub"); + + public void testPreferPrivateKeyDataOverFile() throws Exception { + ConfigBag config = ConfigBag.newInstance(); + config.put(LocationConfigKeys.PRIVATE_KEY_DATA, "mydata"); + config.put(LocationConfigKeys.PRIVATE_KEY_FILE, SSH_PRIVATE_KEY_FILE); + + LocationConfigUtils.OsCredential creds = LocationConfigUtils.getOsCredential(config).doKeyValidation(false); + Assert.assertTrue(creds.hasKey()); + // warnings, as it is malformed + Assert.assertFalse(creds.getWarningMessages().isEmpty()); + + String data = creds.getPrivateKeyData(); + assertEquals(data, "mydata"); + } + + @Test(expectedExceptions=IllegalStateException.class) + public void testInvalidKeyData() throws Exception { + ConfigBag config = ConfigBag.newInstance(); + config.put(LocationConfigKeys.PRIVATE_KEY_DATA, "mydata"); + + LocationConfigUtils.OsCredential creds = LocationConfigUtils.getOsCredential(config).doKeyValidation(false); + Assert.assertTrue(creds.hasKey()); + Assert.assertFalse(creds.getWarningMessages().isEmpty()); + + creds.checkNoErrors(); + } + + public void testPreferPublicKeyDataOverFileAndNoPrivateKeyRequired() throws Exception { + ConfigBag config = ConfigBag.newInstance(); + config.put(LocationConfigKeys.PUBLIC_KEY_DATA, "mydata"); + config.put(LocationConfigKeys.PUBLIC_KEY_FILE, SSH_PUBLIC_KEY_FILE); + config.put(LocationConfigKeys.PRIVATE_KEY_FILE, ""); + + LocationConfigUtils.OsCredential creds = LocationConfigUtils.getOsCredential(config); + String data = creds.getPublicKeyData(); + assertEquals(data, "mydata"); + Assert.assertNull(creds.getPreferredCredential()); + Assert.assertFalse(creds.hasPassword()); + Assert.assertFalse(creds.hasKey()); + // and not even any warnings here + Assert.assertTrue(creds.getWarningMessages().isEmpty()); + } + + @Test(groups="Integration") // requires ~/.ssh/id_rsa + public void testReadsPrivateKeyFileWithTildePath() throws Exception { + ConfigBag config = ConfigBag.newInstance(); + config.put(LocationConfigKeys.PRIVATE_KEY_FILE, SSH_PRIVATE_KEY_FILE_WITH_TILDE); + + // don't mind if it has a passphrase + String data = LocationConfigUtils.getOsCredential(config).doKeyValidation(false).getPreferredCredential(); + assertTrue(data != null && data.length() > 0); + } + + @Test(groups="Integration") + public void testReadsPrivateKeyFileWithPassphrase() throws Exception { + ConfigBag config = ConfigBag.newInstance(); + config.put(LocationConfigKeys.PRIVATE_KEY_FILE, SSH_PRIVATE_KEY_FILE_WITH_PASSPHRASE); + + LocationConfigUtils.OsCredential cred = LocationConfigUtils.getOsCredential(config).doKeyValidation(false); + String data = cred.getPreferredCredential(); + assertTrue(data != null && data.length() > 0); + Assert.assertFalse(data.isEmpty()); + + cred.doKeyValidation(true); + try { + cred.checkNoErrors(); + Assert.fail("check should fail as passphrase needed"); + } catch (IllegalStateException exception) { + } + + config.put(LocationConfigKeys.PRIVATE_KEY_PASSPHRASE, "passphrase"); + cred.checkNoErrors(); + + config.put(LocationConfigKeys.PRIVATE_KEY_PASSPHRASE, "wrong_passphrase"); + try { + cred.checkNoErrors(); + Assert.fail("check should fail as passphrase needed"); + } catch (IllegalStateException exception) { + } + } + + public void testReadsPrivateKeyFileWithMultipleColonSeparatedFilesWithGoodLast() throws Exception { + ConfigBag config = ConfigBag.newInstance(); + config.put(LocationConfigKeys.PRIVATE_KEY_FILE, "/path/does/not/exist"+File.pathSeparator+SSH_PRIVATE_KEY_FILE); + + String data = LocationConfigUtils.getOsCredential(config).getPreferredCredential(); + assertTrue(data != null && data.length() > 0); + } + + public void testReadsPrivateKeyFileWithMultipleColonSeparatedFilesWithGoodFirst() throws Exception { + ConfigBag config = ConfigBag.newInstance(); + config.put(LocationConfigKeys.PRIVATE_KEY_FILE, SSH_PRIVATE_KEY_FILE+File.pathSeparator+"/path/does/not/exist"); + + String data = LocationConfigUtils.getOsCredential(config).getPreferredCredential(); + assertTrue(data != null && data.length() > 0); + } + + @Test(groups="Integration") // requires ~/.ssh/id_rsa + public void testReadsPublicKeyFileWithTildePath() throws Exception { + ConfigBag config = ConfigBag.newInstance(); + config.put(LocationConfigKeys.PUBLIC_KEY_FILE, SSH_PUBLIC_KEY_FILE_WITH_TILDE); + + // don't mind if it has a passphrase + String data = LocationConfigUtils.getOsCredential(config).doKeyValidation(false).getPublicKeyData(); + assertTrue(data != null && data.length() > 0); + } + + public void testInfersPublicKeyFileFromPrivateKeyFile() throws Exception { + ConfigBag config = ConfigBag.newInstance(); + config.put(LocationConfigKeys.PRIVATE_KEY_FILE, SSH_PRIVATE_KEY_FILE); + + String data = LocationConfigUtils.getOsCredential(config).getPublicKeyData(); + assertTrue(data != null && data.length() > 0); + } +} http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a1ad34d7/core/src/test/java/org/apache/brooklyn/location/core/LocationExtensionsTest.java ---------------------------------------------------------------------- diff --git a/core/src/test/java/org/apache/brooklyn/location/core/LocationExtensionsTest.java b/core/src/test/java/org/apache/brooklyn/location/core/LocationExtensionsTest.java new file mode 100644 index 0000000..3b784e2 --- /dev/null +++ b/core/src/test/java/org/apache/brooklyn/location/core/LocationExtensionsTest.java @@ -0,0 +1,187 @@ +/* + * 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 org.apache.brooklyn.location.core; + +import static org.testng.Assert.assertEquals; +import static org.testng.Assert.assertFalse; +import static org.testng.Assert.assertTrue; +import static org.testng.Assert.fail; + +import org.apache.brooklyn.api.location.Location; +import org.apache.brooklyn.api.location.LocationSpec; +import org.apache.brooklyn.api.mgmt.ManagementContext; +import org.apache.brooklyn.core.test.entity.LocalManagementContextForTests; +import org.apache.brooklyn.entity.core.Entities; +import org.apache.brooklyn.location.core.AbstractLocation; +import org.testng.annotations.AfterMethod; +import org.testng.annotations.BeforeMethod; +import org.testng.annotations.Test; + +public class LocationExtensionsTest { + + public static class ConcreteLocation extends AbstractLocation { + private static final long serialVersionUID = 2407231019435442876L; + + public ConcreteLocation() { + super(); + } + } + + public interface MyExtension { + } + + public static class MyExtensionImpl implements MyExtension { + } + + private ManagementContext mgmt; + + @BeforeMethod(alwaysRun=true) + public void setUp() throws Exception { + mgmt = new LocalManagementContextForTests(); + } + + @AfterMethod(alwaysRun = true) + public void tearDown(){ + if (mgmt!=null) Entities.destroyAll(mgmt); + } + + private ConcreteLocation createConcrete() { + return mgmt.getLocationManager().createLocation(LocationSpec.create(ConcreteLocation.class)); + } + + @SuppressWarnings({ "unchecked", "rawtypes" }) + private ConcreteLocation createConcrete(Class<?> extensionType, Object extension) { + // this cast is needed to make IntelliJ happy + return (ConcreteLocation) mgmt.getLocationManager().createLocation(LocationSpec.create(ConcreteLocation.class).extension((Class)extensionType, extension)); + } + + @Test + public void testHasExtensionWhenMissing() { + Location loc = createConcrete(); + assertFalse(loc.hasExtension(MyExtension.class)); + } + + @Test + public void testWhenExtensionPresent() { + MyExtension extension = new MyExtensionImpl(); + ConcreteLocation loc = createConcrete(); + loc.addExtension(MyExtension.class, extension); + + assertTrue(loc.hasExtension(MyExtension.class)); + assertEquals(loc.getExtension(MyExtension.class), extension); + } + + @Test + public void testAddExtensionThroughLocationSpec() { + MyExtension extension = new MyExtensionImpl(); + Location loc = createConcrete(MyExtension.class, extension); + + assertTrue(loc.hasExtension(MyExtension.class)); + assertEquals(loc.getExtension(MyExtension.class), extension); + } + + @Test + public void testGetExtensionWhenMissing() { + Location loc = createConcrete(); + + try { + loc.getExtension(MyExtension.class); + fail(); + } catch (IllegalArgumentException e) { + // success + } + + try { + loc.getExtension(null); + fail(); + } catch (NullPointerException e) { + // success + } + } + + @Test + public void testWhenExtensionDifferent() { + MyExtension extension = new MyExtensionImpl(); + ConcreteLocation loc = createConcrete(); + loc.addExtension(MyExtension.class, extension); + + assertFalse(loc.hasExtension(Object.class)); + + try { + loc.getExtension(Object.class); + fail(); + } catch (IllegalArgumentException e) { + // success + } + } + + @Test + @SuppressWarnings({ "unchecked", "rawtypes" }) + public void testAddExtensionIllegally() { + MyExtension extension = new MyExtensionImpl(); + ConcreteLocation loc = createConcrete(); + + try { + loc.addExtension((Class)MyExtension.class, "not an extension"); + fail(); + } catch (IllegalArgumentException e) { + // success + } + + try { + loc.addExtension(MyExtension.class, null); + fail(); + } catch (NullPointerException e) { + // success + } + + try { + loc.addExtension(null, extension); + fail(); + } catch (NullPointerException e) { + // success + } + } + + @Test + public void testAddExtensionThroughLocationSpecIllegally() { + MyExtension extension = new MyExtensionImpl(); + + try { + Location loc = createConcrete(MyExtension.class, "not an extension"); + fail("loc="+loc); + } catch (IllegalArgumentException e) { + // success + } + + try { + Location loc = createConcrete(MyExtension.class, null); + fail("loc="+loc); + } catch (NullPointerException e) { + // success + } + + try { + Location loc = createConcrete(null, extension); + fail("loc="+loc); + } catch (NullPointerException e) { + // success + } + } +} http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a1ad34d7/core/src/test/java/org/apache/brooklyn/location/core/LocationManagementTest.java ---------------------------------------------------------------------- diff --git a/core/src/test/java/org/apache/brooklyn/location/core/LocationManagementTest.java b/core/src/test/java/org/apache/brooklyn/location/core/LocationManagementTest.java new file mode 100644 index 0000000..78a8cfc --- /dev/null +++ b/core/src/test/java/org/apache/brooklyn/location/core/LocationManagementTest.java @@ -0,0 +1,82 @@ +/* + * 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 org.apache.brooklyn.location.core; + +import static org.testng.Assert.assertEquals; +import static org.testng.Assert.assertFalse; +import static org.testng.Assert.assertNull; +import static org.testng.Assert.assertSame; +import static org.testng.Assert.assertTrue; + +import org.apache.brooklyn.api.location.LocationSpec; +import org.apache.brooklyn.api.mgmt.LocationManager; +import org.apache.brooklyn.core.test.BrooklynAppUnitTestSupport; +import org.apache.brooklyn.location.byon.FixedListMachineProvisioningLocation; +import org.apache.brooklyn.location.ssh.SshMachineLocation; +import org.testng.annotations.BeforeMethod; +import org.testng.annotations.Test; + +import com.google.common.collect.ImmutableMap; +import com.google.common.collect.Iterables; + +public class LocationManagementTest extends BrooklynAppUnitTestSupport { + + private LocationManager locationManager; + + @BeforeMethod(alwaysRun=true) + @Override + public void setUp() throws Exception { + super.setUp(); + locationManager = mgmt.getLocationManager(); + } + + @Test + public void testCreateLocationUsingSpec() { + SshMachineLocation loc = locationManager.createLocation(LocationSpec.create(SshMachineLocation.class) + .configure("address", "1.2.3.4")); + + assertEquals(loc.getAddress().getHostAddress(), "1.2.3.4"); + assertSame(locationManager.getLocation(loc.getId()), loc); + } + + @Test + public void testCreateLocationUsingResolver() { + String spec = "byon:(hosts=\"1.1.1.1\")"; + FixedListMachineProvisioningLocation<SshMachineLocation> loc = (FixedListMachineProvisioningLocation<SshMachineLocation>) mgmt.getLocationRegistry().resolve(spec); + SshMachineLocation machine = Iterables.getOnlyElement(loc.getAllMachines()); + + assertSame(locationManager.getLocation(loc.getId()), loc); + assertSame(locationManager.getLocation(machine.getId()), machine); + } + + @Test + public void testChildrenOfManagedLocationAutoManaged() { + String spec = "byon:(hosts=\"1.1.1.1\")"; + FixedListMachineProvisioningLocation<SshMachineLocation> loc = (FixedListMachineProvisioningLocation<SshMachineLocation>) mgmt.getLocationRegistry().resolve(spec); + SshMachineLocation machine = new SshMachineLocation(ImmutableMap.of("address", "1.2.3.4")); + + loc.addChild(machine); + assertSame(locationManager.getLocation(machine.getId()), machine); + assertTrue(machine.isManaged()); + + loc.removeChild(machine); + assertNull(locationManager.getLocation(machine.getId())); + assertFalse(machine.isManaged()); + } +} http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a1ad34d7/core/src/test/java/org/apache/brooklyn/location/core/LocationPredicatesTest.java ---------------------------------------------------------------------- diff --git a/core/src/test/java/org/apache/brooklyn/location/core/LocationPredicatesTest.java b/core/src/test/java/org/apache/brooklyn/location/core/LocationPredicatesTest.java new file mode 100644 index 0000000..d63aaac --- /dev/null +++ b/core/src/test/java/org/apache/brooklyn/location/core/LocationPredicatesTest.java @@ -0,0 +1,102 @@ +/* + * 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 org.apache.brooklyn.location.core; + +import static org.testng.Assert.assertFalse; +import static org.testng.Assert.assertTrue; + +import org.apache.brooklyn.api.location.Location; +import org.apache.brooklyn.api.location.LocationSpec; +import org.apache.brooklyn.core.mgmt.internal.LocalManagementContext; +import org.apache.brooklyn.core.test.entity.LocalManagementContextForTests; +import org.apache.brooklyn.core.test.entity.TestEntity; +import org.apache.brooklyn.entity.core.Entities; +import org.apache.brooklyn.location.core.LocationPredicates; +import org.apache.brooklyn.location.core.Locations; +import org.apache.brooklyn.location.localhost.LocalhostMachineProvisioningLocation; +import org.apache.brooklyn.location.ssh.SshMachineLocation; +import org.testng.annotations.AfterMethod; +import org.testng.annotations.BeforeMethod; +import org.testng.annotations.Test; + +public class LocationPredicatesTest { + + private LocalManagementContext managementContext; + private LocalhostMachineProvisioningLocation loc; + private SshMachineLocation childLoc; + private Location grandchildLoc; + + @BeforeMethod(alwaysRun=true) + public void setUp() throws Exception { + managementContext = LocalManagementContextForTests.newInstance(); + loc = (LocalhostMachineProvisioningLocation) managementContext.getLocationRegistry().resolve("localhost:(name=mydisplayname)"); + childLoc = loc.obtain(); + grandchildLoc = managementContext.getLocationManager().createLocation(LocationSpec.create(SimulatedLocation.class).parent(childLoc)); + } + + @AfterMethod(alwaysRun=true) + public void tearDown() throws Exception { + if (managementContext != null) Entities.destroyAll(managementContext); + } + + @Test + public void testIdEqualTo() throws Exception { + assertTrue(LocationPredicates.idEqualTo(loc.getId()).apply(loc)); + assertFalse(LocationPredicates.idEqualTo("wrongid").apply(loc)); + } + + @Test + public void testConfigEqualTo() throws Exception { + loc.setConfig(TestEntity.CONF_NAME, "myname"); + assertTrue(LocationPredicates.configEqualTo(TestEntity.CONF_NAME, "myname").apply(loc)); + assertFalse(LocationPredicates.configEqualTo(TestEntity.CONF_NAME, "wrongname").apply(loc)); + } + + @Test + public void testDisplayNameEqualTo() throws Exception { + assertTrue(LocationPredicates.displayNameEqualTo("mydisplayname").apply(loc)); + assertFalse(LocationPredicates.displayNameEqualTo("wrongname").apply(loc)); + } + + @Test + public void testIsChildOf() throws Exception { + assertTrue(LocationPredicates.isChildOf(loc).apply(childLoc)); + assertFalse(LocationPredicates.isChildOf(loc).apply(loc)); + assertFalse(LocationPredicates.isChildOf(childLoc).apply(loc)); + } + + @Test + public void testIsDescendantOf() throws Exception { + assertTrue(LocationPredicates.isDescendantOf(loc).apply(grandchildLoc)); + assertTrue(LocationPredicates.isDescendantOf(loc).apply(childLoc)); + assertFalse(LocationPredicates.isDescendantOf(loc).apply(loc)); + assertFalse(LocationPredicates.isDescendantOf(childLoc).apply(loc)); + } + + @Test + public void testManaged() throws Exception { + // TODO get exception in LocalhostMachineProvisioningLocation.removeChild because childLoc is "in use"; + // this happens from the call to unmanage(loc), which first unmanaged the children. + loc.release(childLoc); + + assertTrue(LocationPredicates.managed().apply(loc)); + Locations.unmanage(loc); + assertFalse(LocationPredicates.managed().apply(loc)); + } +} http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a1ad34d7/core/src/test/java/org/apache/brooklyn/location/core/LocationPropertiesFromBrooklynPropertiesTest.java ---------------------------------------------------------------------- diff --git a/core/src/test/java/org/apache/brooklyn/location/core/LocationPropertiesFromBrooklynPropertiesTest.java b/core/src/test/java/org/apache/brooklyn/location/core/LocationPropertiesFromBrooklynPropertiesTest.java new file mode 100644 index 0000000..f9e12ab --- /dev/null +++ b/core/src/test/java/org/apache/brooklyn/location/core/LocationPropertiesFromBrooklynPropertiesTest.java @@ -0,0 +1,122 @@ +/* + * 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 org.apache.brooklyn.location.core; + +import static org.testng.Assert.assertEquals; + +import java.util.Map; + +import org.apache.brooklyn.location.core.LocationPropertiesFromBrooklynProperties; +import org.testng.annotations.BeforeMethod; +import org.testng.annotations.Test; + +import com.google.common.collect.Maps; + +public class LocationPropertiesFromBrooklynPropertiesTest { + + private LocationPropertiesFromBrooklynProperties parser; + + @BeforeMethod(alwaysRun=true) + public void setUp() throws Exception { + parser = new LocationPropertiesFromBrooklynProperties(); + } + + @Test + public void testExtractProviderProperties() throws Exception { + String provider = "myprovider"; + String namedLocation = null; + + Map<String, String> properties = Maps.newLinkedHashMap(); + + // prefer those in "named" over everything else + properties.put("brooklyn.location.myprovider.privateKeyFile", "privateKeyFile-inProviderSpecific"); + properties.put("brooklyn.location.privateKeyFile", "privateKeyFile-inLocationGeneric"); + + // prefer location-generic if nothing else + properties.put("brooklyn.location.publicKeyFile", "publicKeyFile-inLocationGeneric"); + + Map<String, Object> conf = parser.getLocationProperties(provider, namedLocation, properties); + assertEquals(conf.get("privateKeyFile"), "privateKeyFile-inProviderSpecific"); + assertEquals(conf.get("publicKeyFile"), "publicKeyFile-inLocationGeneric"); + } + + @Test + public void testExtractNamedLocationProperties() throws Exception { + String provider = "myprovider"; + String namedLocation = "mynamed"; + + Map<String, String> properties = Maps.newLinkedHashMap(); + + properties.put("brooklyn.location.named.mynamed", "myprovider"); + + // prefer those in "named" over everything else + properties.put("brooklyn.location.named.mynamed.privateKeyFile", "privateKeyFile-inNamed"); + properties.put("brooklyn.location.myprovider.privateKeyFile", "privateKeyFile-inProviderSpecific"); + properties.put("brooklyn.location.privateKeyFile", "privateKeyFile-inGeneric"); + + // prefer those in provider-specific over generic + properties.put("brooklyn.location.myprovider.publicKeyFile", "publicKeyFile-inProviderSpecific"); + properties.put("brooklyn.location.publicKeyFile", "publicKeyFile-inGeneric"); + + // prefer location-generic if nothing else + properties.put("brooklyn.location.privateKeyData", "privateKeyData-inGeneric"); + + Map<String, Object> conf = parser.getLocationProperties(provider, namedLocation, properties); + assertEquals(conf.get("privateKeyFile"), "privateKeyFile-inNamed"); + assertEquals(conf.get("publicKeyFile"), "publicKeyFile-inProviderSpecific"); + assertEquals(conf.get("privateKeyData"), "privateKeyData-inGeneric"); + } + + @Test + public void testConvertsDeprecatedFormats() throws Exception { + String provider = "myprovider"; + String namedLocation = "mynamed"; + + Map<String, String> properties = Maps.newLinkedHashMap(); + + properties.put("brooklyn.location.named.mynamed", "myprovider"); + + // prefer those in "named" over everything else + properties.put("brooklyn.location.named.mynamed.private-key-file", "privateKeyFile-inNamed"); + properties.put("brooklyn.location.myprovider.public-key-file", "publicKeyFile-inProviderSpecific"); + properties.put("brooklyn.location.private-key-data", "privateKeyData-inGeneric"); + + Map<String, Object> conf = parser.getLocationProperties(provider, namedLocation, properties); + assertEquals(conf.get("privateKeyFile"), "privateKeyFile-inNamed"); + assertEquals(conf.get("publicKeyFile"), "publicKeyFile-inProviderSpecific"); + assertEquals(conf.get("privateKeyData"), "privateKeyData-inGeneric"); + } + + + @Test + public void testThrowsIfProviderDoesNotMatchNamed() throws Exception { + String provider = "myprovider"; + String namedLocation = "mynamed"; + + Map<String, String> properties = Maps.newLinkedHashMap(); + + properties.put("brooklyn.location.named.mynamed", "completelydifferent"); + + try { + Map<String, Object> conf = parser.getLocationProperties(provider, namedLocation, properties); + } catch (IllegalStateException e) { + if (!e.toString().contains("Conflicting configuration")) throw e; + } + } +} http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a1ad34d7/core/src/test/java/org/apache/brooklyn/location/core/LocationRegistryTest.java ---------------------------------------------------------------------- diff --git a/core/src/test/java/org/apache/brooklyn/location/core/LocationRegistryTest.java b/core/src/test/java/org/apache/brooklyn/location/core/LocationRegistryTest.java new file mode 100644 index 0000000..8520403 --- /dev/null +++ b/core/src/test/java/org/apache/brooklyn/location/core/LocationRegistryTest.java @@ -0,0 +1,161 @@ +/* + * 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 org.apache.brooklyn.location.core; + +import org.apache.brooklyn.api.location.Location; +import org.apache.brooklyn.api.location.LocationDefinition; +import org.apache.brooklyn.core.internal.BrooklynProperties; +import org.apache.brooklyn.core.mgmt.internal.LocalManagementContext; +import org.apache.brooklyn.core.test.entity.LocalManagementContextForTests; +import org.apache.brooklyn.entity.core.Entities; +import org.apache.brooklyn.location.byon.FixedListMachineProvisioningLocation; +import org.apache.brooklyn.location.core.BasicLocationRegistry; +import org.apache.brooklyn.location.core.LocationConfigKeys; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.testng.Assert; +import org.testng.annotations.AfterMethod; +import org.testng.annotations.Test; + +public class LocationRegistryTest { + + private static final Logger log = LoggerFactory.getLogger(LocationRegistryTest.class); + + private LocalManagementContext mgmt; + private LocationDefinition locdef; + + @AfterMethod(alwaysRun = true) + public void tearDown(){ + if (mgmt != null) Entities.destroyAll(mgmt); + } + + @Test + public void testNamedLocationsPropertyDefinedLocations() { + BrooklynProperties properties = BrooklynProperties.Factory.newEmpty(); + properties.put("brooklyn.location.named.foo", "byon:(hosts=\"[email protected].{1,2,3,4}\")"); + properties.put("brooklyn.location.named.foo.privateKeyFile", "~/.ssh/foo.id_rsa"); + mgmt = LocalManagementContextForTests.newInstance(properties); + log.info("foo properties gave defined locations: "+mgmt.getLocationRegistry().getDefinedLocations()); + locdef = mgmt.getLocationRegistry().getDefinedLocationByName("foo"); + Assert.assertNotNull(locdef, "Expected 'foo' location; but had "+mgmt.getLocationRegistry().getDefinedLocations()); + Assert.assertEquals(locdef.getConfig().get("privateKeyFile"), "~/.ssh/foo.id_rsa"); + } + + @Test(dependsOnMethods="testNamedLocationsPropertyDefinedLocations") + public void testResolvesByNamedAndId() { + BrooklynProperties properties = BrooklynProperties.Factory.newEmpty(); + properties.put("brooklyn.location.named.foo", "byon:(hosts=\"[email protected].{1,2,3,4}\")"); + properties.put("brooklyn.location.named.foo.privateKeyFile", "~/.ssh/foo.id_rsa"); + mgmt = LocalManagementContextForTests.newInstance(properties); + + locdef = mgmt.getLocationRegistry().getDefinedLocationByName("foo"); + log.info("testResovlesBy has defined locations: "+mgmt.getLocationRegistry().getDefinedLocations()); + + Location l = mgmt.getLocationRegistry().resolve("named:foo"); + Assert.assertNotNull(l); + Assert.assertEquals(l.getConfig(LocationConfigKeys.PRIVATE_KEY_FILE), "~/.ssh/foo.id_rsa"); + + l = mgmt.getLocationRegistry().resolve("foo"); + Assert.assertNotNull(l); + Assert.assertEquals(l.getConfig(LocationConfigKeys.PRIVATE_KEY_FILE), "~/.ssh/foo.id_rsa"); + + l = mgmt.getLocationRegistry().resolve("id:"+locdef.getId()); + Assert.assertNotNull(l); + Assert.assertEquals(l.getConfig(LocationConfigKeys.PRIVATE_KEY_FILE), "~/.ssh/foo.id_rsa"); + + l = mgmt.getLocationRegistry().resolve(locdef.getId()); + Assert.assertNotNull(l); + Assert.assertEquals(l.getConfig(LocationConfigKeys.PRIVATE_KEY_FILE), "~/.ssh/foo.id_rsa"); + } + + @Test + public void testLocationGetsDisplayName() { + BrooklynProperties properties = BrooklynProperties.Factory.newEmpty(); + properties.put("brooklyn.location.named.foo", "byon:(hosts=\"[email protected].{1,2,3,4}\")"); + properties.put("brooklyn.location.named.foo.displayName", "My Foo"); + mgmt = LocalManagementContextForTests.newInstance(properties); + Location l = mgmt.getLocationRegistry().resolve("foo"); + Assert.assertEquals(l.getDisplayName(), "My Foo"); + } + + @Test + public void testLocationGetsDefaultDisplayName() { + BrooklynProperties properties = BrooklynProperties.Factory.newEmpty(); + properties.put("brooklyn.location.named.foo", "byon:(hosts=\"[email protected].{1,2,3,4}\")"); + mgmt = LocalManagementContextForTests.newInstance(properties); + Location l = mgmt.getLocationRegistry().resolve("foo"); + Assert.assertNotNull(l.getDisplayName()); + Assert.assertTrue(l.getDisplayName().startsWith(FixedListMachineProvisioningLocation.class.getSimpleName()), "name="+l.getDisplayName()); + // TODO currently it gives default name; it would be nice to use 'foo', + // or at least to have access to the spec (and use it e.g. in places such as DynamicFabric) + // Assert.assertEquals(l.getDisplayName(), "foo"); + } + + @Test + public void testSetupForTesting() { + mgmt = LocalManagementContextForTests.newInstance(); + BasicLocationRegistry.setupLocationRegistryForTesting(mgmt); + Assert.assertNotNull(mgmt.getLocationRegistry().getDefinedLocationByName("localhost")); + } + + @Test + public void testCircularReference() { + BrooklynProperties properties = BrooklynProperties.Factory.newEmpty(); + properties.put("brooklyn.location.named.bar", "named:bar"); + mgmt = LocalManagementContextForTests.newInstance(properties); + log.info("bar properties gave defined locations: "+mgmt.getLocationRegistry().getDefinedLocations()); + boolean resolved = false; + try { + mgmt.getLocationRegistry().resolve("bar"); + resolved = true; + } catch (IllegalStateException e) { + //expected + log.info("bar properties correctly caught circular reference: "+e); + } + if (resolved) + // probably won't happen, if test fails will loop endlessly above + Assert.fail("Circular reference resolved location"); + } + + protected boolean findLocationMatching(String regex) { + for (LocationDefinition d: mgmt.getLocationRegistry().getDefinedLocations().values()) { + if (d.getName()!=null && d.getName().matches(regex)) return true; + } + return false; + } + + @Test + public void testLocalhostEnabled() { + BrooklynProperties properties = BrooklynProperties.Factory.newEmpty(); + properties.put("brooklyn.location.localhost.enabled", true); + mgmt = LocalManagementContextForTests.newInstance(properties); + Assert.assertTrue( findLocationMatching("localhost") ); + } + + @Test + public void testLocalhostDisabled() { + BrooklynProperties properties = BrooklynProperties.Factory.newEmpty(); + properties.put("brooklyn.location.localhost.enabled", false); + mgmt = LocalManagementContextForTests.newInstance(properties); + log.info("RESOLVERS: "+mgmt.getLocationRegistry().getDefinedLocations()); + log.info("DEFINED LOCATIONS: "+mgmt.getLocationRegistry().getDefinedLocations()); + Assert.assertFalse( findLocationMatching("localhost") ); + } + +} http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a1ad34d7/core/src/test/java/org/apache/brooklyn/location/core/MachineDetailsTest.java ---------------------------------------------------------------------- diff --git a/core/src/test/java/org/apache/brooklyn/location/core/MachineDetailsTest.java b/core/src/test/java/org/apache/brooklyn/location/core/MachineDetailsTest.java new file mode 100644 index 0000000..9a02212 --- /dev/null +++ b/core/src/test/java/org/apache/brooklyn/location/core/MachineDetailsTest.java @@ -0,0 +1,83 @@ +/* + * 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 org.apache.brooklyn.location.core; + +import static org.testng.Assert.assertFalse; +import static org.testng.Assert.assertNotNull; + +import java.util.Arrays; + +import org.apache.brooklyn.api.location.LocationSpec; +import org.apache.brooklyn.api.location.MachineDetails; +import org.apache.brooklyn.api.location.OsDetails; +import org.apache.brooklyn.api.mgmt.ManagementContext; +import org.apache.brooklyn.api.mgmt.Task; +import org.apache.brooklyn.core.test.entity.TestApplication; +import org.apache.brooklyn.entity.core.Entities; +import org.apache.brooklyn.location.core.BasicMachineDetails; +import org.apache.brooklyn.location.localhost.LocalhostMachineProvisioningLocation; +import org.apache.brooklyn.location.ssh.SshMachineLocation; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.testng.annotations.AfterMethod; +import org.testng.annotations.BeforeMethod; +import org.testng.annotations.Test; + +public class MachineDetailsTest { + + private static final Logger LOG = LoggerFactory.getLogger(MachineDetailsTest.class); + + TestApplication app; + ManagementContext mgmt; + SshMachineLocation host; + + @BeforeMethod(alwaysRun=true) + public void setup() throws Exception { + app = TestApplication.Factory.newManagedInstanceForTests(); + mgmt = app.getManagementContext(); + + LocalhostMachineProvisioningLocation localhost = mgmt.getLocationManager().createLocation( + LocationSpec.create(LocalhostMachineProvisioningLocation.class)); + host = localhost.obtain(); + app.start(Arrays.asList(host)); + } + + @AfterMethod(alwaysRun=true) + public void tearDown() throws Exception { + if (mgmt != null) Entities.destroyAll(mgmt); + mgmt = null; + } + + @Test(groups = "Integration") + public void testGetMachineDetails() { + Task<BasicMachineDetails> detailsTask = app.getExecutionContext().submit( + BasicMachineDetails.taskForSshMachineLocation(host)); + MachineDetails machine = detailsTask.getUnchecked(); + LOG.info("Found the following on localhost: {}", machine); + assertNotNull(machine); + OsDetails details = machine.getOsDetails(); + assertNotNull(details); + assertNotNull(details.getArch()); + assertNotNull(details.getName()); + assertNotNull(details.getVersion()); + assertFalse(details.getArch().startsWith("architecture:"), "architecture prefix not removed from details"); + assertFalse(details.getName().startsWith("name:"), "name prefix not removed from details"); + assertFalse(details.getVersion().startsWith("version:"), "version prefix not removed from details"); + } +} http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a1ad34d7/core/src/test/java/org/apache/brooklyn/location/core/MultiLocationRebindTest.java ---------------------------------------------------------------------- diff --git a/core/src/test/java/org/apache/brooklyn/location/core/MultiLocationRebindTest.java b/core/src/test/java/org/apache/brooklyn/location/core/MultiLocationRebindTest.java new file mode 100644 index 0000000..98d50a3 --- /dev/null +++ b/core/src/test/java/org/apache/brooklyn/location/core/MultiLocationRebindTest.java @@ -0,0 +1,122 @@ +/* + * 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 org.apache.brooklyn.location.core; + +import java.io.File; +import java.util.List; + +import org.apache.brooklyn.api.entity.EntitySpec; +import org.apache.brooklyn.api.location.Location; +import org.apache.brooklyn.api.location.LocationSpec; +import org.apache.brooklyn.api.mgmt.ManagementContext; +import org.apache.brooklyn.core.mgmt.rebind.RebindTestUtils; +import org.apache.brooklyn.core.test.entity.TestApplication; +import org.apache.brooklyn.entity.core.Entities; +import org.apache.brooklyn.entity.factory.ApplicationBuilder; +import org.apache.brooklyn.location.byon.FixedListMachineProvisioningLocation; +import org.apache.brooklyn.location.cloud.AvailabilityZoneExtension; +import org.apache.brooklyn.location.core.MultiLocation; +import org.apache.brooklyn.location.ssh.SshMachineLocation; +import org.apache.brooklyn.test.Asserts; +import org.apache.brooklyn.util.collections.MutableSet; +import org.apache.brooklyn.util.net.Networking; +import org.apache.brooklyn.util.os.Os; +import org.testng.annotations.AfterMethod; +import org.testng.annotations.BeforeMethod; +import org.testng.annotations.Test; + +import com.google.common.base.Function; +import com.google.common.base.Predicates; +import com.google.common.collect.ImmutableList; +import com.google.common.collect.Iterables; + +public class MultiLocationRebindTest { + + private ClassLoader classLoader = getClass().getClassLoader(); + private ManagementContext origManagementContext; + private ManagementContext newManagementContext; + private File mementoDir; + + private TestApplication origApp; + private TestApplication newApp; + private SshMachineLocation mac1a; + private SshMachineLocation mac2a; + private FixedListMachineProvisioningLocation<SshMachineLocation> loc1; + private FixedListMachineProvisioningLocation<SshMachineLocation> loc2; + private MultiLocation<SshMachineLocation> multiLoc; + + @BeforeMethod(alwaysRun=true) + public void setUp() throws Exception { + mementoDir = Os.newTempDir(getClass()); + origManagementContext = RebindTestUtils.newPersistingManagementContext(mementoDir, classLoader, 1); + origApp = ApplicationBuilder.newManagedApp(EntitySpec.create(TestApplication.class), origManagementContext); + } + + @AfterMethod(alwaysRun=true) + public void tearDown() throws Exception { + if (origManagementContext != null) Entities.destroyAll(origManagementContext); + if (newApp != null) Entities.destroyAll(newApp.getManagementContext()); + if (newManagementContext != null) Entities.destroyAll(newManagementContext); + if (mementoDir != null) RebindTestUtils.deleteMementoDir(mementoDir); + } + + @SuppressWarnings("unchecked") + @Test + public void testRebindsMultiLocation() throws Exception { + mac1a = origManagementContext.getLocationManager().createLocation(LocationSpec.create(SshMachineLocation.class) + .displayName("mac1a") + .configure("address", Networking.getInetAddressWithFixedName("1.1.1.1"))); + mac2a = origManagementContext.getLocationManager().createLocation(LocationSpec.create(SshMachineLocation.class) + .displayName("mac2a") + .configure("address", Networking.getInetAddressWithFixedName("1.1.1.3"))); + loc1 = origManagementContext.getLocationManager().createLocation(LocationSpec.create(FixedListMachineProvisioningLocation.class) + .displayName("loc1") + .configure("machines", MutableSet.of(mac1a))); + loc2 = origManagementContext.getLocationManager().createLocation(LocationSpec.create(FixedListMachineProvisioningLocation.class) + .displayName("loc2") + .configure("machines", MutableSet.of(mac2a))); + multiLoc = origManagementContext.getLocationManager().createLocation(LocationSpec.create(MultiLocation.class) + .displayName("multiLoc") + .configure("subLocations", ImmutableList.of(loc1, loc2))); + + newApp = rebind(); + newManagementContext = newApp.getManagementContext(); + + MultiLocation newMultiLoc = (MultiLocation) Iterables.find(newManagementContext.getLocationManager().getLocations(), Predicates.instanceOf(MultiLocation.class)); + AvailabilityZoneExtension azExtension = newMultiLoc.getExtension(AvailabilityZoneExtension.class); + List<Location> newSublLocs = azExtension.getAllSubLocations(); + Iterable<String> newSubLocNames = Iterables.transform(newSublLocs, new Function<Location, String>() { + @Override public String apply(Location input) { + return (input == null) ? null : input.getDisplayName(); + }}); + Asserts.assertEqualsIgnoringOrder(newSubLocNames, ImmutableList.of("loc1", "loc2")); + } + + private TestApplication rebind() throws Exception { + return rebind(true); + } + + private TestApplication rebind(boolean checkSerializable) throws Exception { + RebindTestUtils.waitForPersisted(origApp); + if (checkSerializable) { + RebindTestUtils.checkCurrentMementoSerializable(origApp); + } + return (TestApplication) RebindTestUtils.rebind(mementoDir, getClass().getClassLoader()); + } +} http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a1ad34d7/core/src/test/java/org/apache/brooklyn/location/core/MultiLocationResolverTest.java ---------------------------------------------------------------------- diff --git a/core/src/test/java/org/apache/brooklyn/location/core/MultiLocationResolverTest.java b/core/src/test/java/org/apache/brooklyn/location/core/MultiLocationResolverTest.java new file mode 100644 index 0000000..42cebc8 --- /dev/null +++ b/core/src/test/java/org/apache/brooklyn/location/core/MultiLocationResolverTest.java @@ -0,0 +1,203 @@ +/* + * 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 org.apache.brooklyn.location.core; + +import static org.testng.Assert.assertEquals; +import static org.testng.Assert.assertFalse; +import static org.testng.Assert.assertTrue; +import static org.testng.Assert.fail; + +import java.net.InetAddress; +import java.util.Collections; +import java.util.Iterator; +import java.util.List; +import java.util.NoSuchElementException; + +import javax.annotation.Nullable; + +import org.apache.brooklyn.api.location.Location; +import org.apache.brooklyn.api.location.MachineLocation; +import org.apache.brooklyn.api.location.MachineProvisioningLocation; +import org.apache.brooklyn.api.location.NoMachinesAvailableException; +import org.apache.brooklyn.core.internal.BrooklynProperties; +import org.apache.brooklyn.core.mgmt.internal.LocalManagementContext; +import org.apache.brooklyn.core.test.entity.LocalManagementContextForTests; +import org.apache.brooklyn.entity.core.Entities; +import org.apache.brooklyn.location.byon.FixedListMachineProvisioningLocation; +import org.apache.brooklyn.location.cloud.AvailabilityZoneExtension; +import org.apache.brooklyn.location.core.LocationPredicates; +import org.apache.brooklyn.location.core.MultiLocation; +import org.apache.brooklyn.location.localhost.LocalhostMachineProvisioningLocation; +import org.apache.brooklyn.location.ssh.SshMachineLocation; +import org.apache.brooklyn.util.collections.MutableList; +import org.apache.brooklyn.util.collections.MutableMap; +import org.apache.brooklyn.util.exceptions.Exceptions; +import org.testng.Assert; +import org.testng.annotations.AfterMethod; +import org.testng.annotations.BeforeMethod; +import org.testng.annotations.Test; + +import com.google.common.base.Objects; +import com.google.common.base.Optional; +import com.google.common.base.Predicate; +import com.google.common.base.Predicates; +import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableMap; +import com.google.common.collect.Iterables; + +public class MultiLocationResolverTest { + + private BrooklynProperties brooklynProperties; + private LocalManagementContext managementContext; + + @BeforeMethod(alwaysRun=true) + public void setUp() throws Exception { + managementContext = LocalManagementContextForTests.newInstance(); + brooklynProperties = managementContext.getBrooklynProperties(); + } + + @AfterMethod(alwaysRun=true) + public void tearDown() throws Exception { + if (managementContext != null) Entities.destroyAll(managementContext); + } + + @Test + public void testThrowsOnInvalid() throws Exception { + assertThrowsNoSuchElement("wrongprefix:(hosts=\"1.1.1.1\")"); + assertThrowsIllegalArgument("single"); + } + + @Test + public void testThrowsOnInvalidTarget() throws Exception { + assertThrowsIllegalArgument("multi:()"); + assertThrowsIllegalArgument("multi:(wrongprefix:(hosts=\"1.1.1.1\"))"); + assertThrowsIllegalArgument("multi:(foo:bar)"); + } + + @Test + public void testCleansUpOnInvalidTarget() { + assertThrowsNoSuchElement("multi:(targets=\"localhost:(name=testCleansUpOnInvalidTarget),thisNamedLocationDoesNotExist\")"); + Optional<Location> subtarget = Iterables.tryFind(managementContext.getLocationManager().getLocations(), LocationPredicates.displayNameEqualTo("testCleansUpOnInvalidTarget")); + assertFalse(subtarget.isPresent(), "subtarget="+subtarget); + } + + + @Test + public void testResolvesSubLocs() { + assertMultiLocation(resolve("multi:(targets=localhost)"), 1, ImmutableList.of(Predicates.instanceOf(LocalhostMachineProvisioningLocation.class))); + assertMultiLocation(resolve("multi:(targets=\"localhost,localhost\")"), 2, Collections.nCopies(2, Predicates.instanceOf(LocalhostMachineProvisioningLocation.class))); + assertMultiLocation(resolve("multi:(targets=\"localhost,localhost,localhost\")"), 3, Collections.nCopies(3, Predicates.instanceOf(LocalhostMachineProvisioningLocation.class))); + assertMultiLocation(resolve("multi:(targets=\"localhost:(name=mysubname)\")"), 1, ImmutableList.of(displayNameEqualTo("mysubname"))); + assertMultiLocation(resolve("multi:(targets=byon:(hosts=\"1.1.1.1\"))"), 1, ImmutableList.of(Predicates.and( + Predicates.instanceOf(FixedListMachineProvisioningLocation.class), + new Predicate<MachineProvisioningLocation>() { + @Override public boolean apply(MachineProvisioningLocation input) { + SshMachineLocation machine; + try { + machine = (SshMachineLocation) input.obtain(ImmutableMap.of()); + } catch (NoMachinesAvailableException e) { + throw Exceptions.propagate(e); + } + try { + String addr = ((SshMachineLocation)machine).getAddress().getHostAddress(); + return addr != null && addr.equals("1.1.1.1"); + } finally { + input.release(machine); + } + } + }))); + assertMultiLocation(resolve("multi:(targets=\"byon:(hosts=1.1.1.1),byon:(hosts=1.1.1.2)\")"), 2, Collections.nCopies(2, Predicates.instanceOf(FixedListMachineProvisioningLocation.class))); + } + + @Test + public void testResolvesName() { + MultiLocation<SshMachineLocation> multiLoc = resolve("multi:(name=myname,targets=localhost)"); + assertEquals(multiLoc.getDisplayName(), "myname"); + } + + @Test + public void testNamedByonLocation() throws Exception { + brooklynProperties.put("brooklyn.location.named.mynamed", "multi:(targets=byon:(hosts=\"1.1.1.1\"))"); + + MultiLocation<SshMachineLocation> loc = resolve("named:mynamed"); + assertEquals(loc.obtain(ImmutableMap.of()).getAddress(), InetAddress.getByName("1.1.1.1")); + } + + @Test + public void testResolvesFromMap() throws NoMachinesAvailableException { + Location l = managementContext.getLocationRegistry().resolve("multi", MutableMap.of("targets", + MutableList.of("localhost", MutableMap.of("byon", MutableMap.of("hosts", "127.0.0.127"))))); + MultiLocation<?> ml = (MultiLocation<?>)l; + Iterator<MachineProvisioningLocation<?>> ci = ml.getSubLocations().iterator(); + + l = ci.next(); + Assert.assertTrue(l instanceof LocalhostMachineProvisioningLocation, "Expected localhost, got "+l); + + l = ci.next(); + Assert.assertTrue(l instanceof FixedListMachineProvisioningLocation, "Expected fixed, got "+l); + MachineLocation sl = ((FixedListMachineProvisioningLocation<?>)l).obtain(); + Assert.assertEquals(sl.getAddress().getHostAddress(), "127.0.0.127"); + + Assert.assertFalse(ci.hasNext()); + } + + + private void assertThrowsNoSuchElement(String val) { + try { + resolve(val); + fail(); + } catch (NoSuchElementException e) { + // success + } + } + + private void assertThrowsIllegalArgument(String val) { + try { + resolve(val); + fail(); + } catch (IllegalArgumentException e) { + // success + } + } + + @SuppressWarnings("unchecked") + private MultiLocation<SshMachineLocation> resolve(String val) { + return (MultiLocation<SshMachineLocation>) managementContext.getLocationRegistry().resolve(val); + } + + @SuppressWarnings("rawtypes") + private void assertMultiLocation(MultiLocation<?> multiLoc, int expectedSize, List<? extends Predicate> expectedSubLocationPredicates) { + AvailabilityZoneExtension zones = multiLoc.getExtension(AvailabilityZoneExtension.class); + List<Location> subLocs = zones.getAllSubLocations(); + assertEquals(subLocs.size(), expectedSize, "zones="+subLocs); + for (int i = 0; i < subLocs.size(); i++) { + MachineProvisioningLocation subLoc = (MachineProvisioningLocation) subLocs.get(i); + assertTrue(expectedSubLocationPredicates.get(i).apply(subLoc), "index="+i+"; subLocs="+subLocs); + } + } + + public static <T> Predicate<Location> displayNameEqualTo(final T val) { + return new Predicate<Location>() { + @Override + public boolean apply(@Nullable Location input) { + return Objects.equal(input.getDisplayName(), val); + } + }; + } +}
