http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a1ad34d7/core/src/test/java/org/apache/brooklyn/location/basic/TestPortSupplierLocation.java ---------------------------------------------------------------------- diff --git a/core/src/test/java/org/apache/brooklyn/location/basic/TestPortSupplierLocation.java b/core/src/test/java/org/apache/brooklyn/location/basic/TestPortSupplierLocation.java deleted file mode 100644 index e7b6963..0000000 --- a/core/src/test/java/org/apache/brooklyn/location/basic/TestPortSupplierLocation.java +++ /dev/null @@ -1,89 +0,0 @@ -/* - * 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.basic; - -import static org.testng.Assert.assertEquals; - -import org.apache.brooklyn.api.entity.EntitySpec; -import org.apache.brooklyn.core.test.BrooklynAppUnitTestSupport; -import org.apache.brooklyn.core.test.entity.TestEntity; -import org.apache.brooklyn.sensor.core.PortAttributeSensorAndConfigKey; -import org.apache.brooklyn.sensor.feed.ConfigToAttributes; -import org.testng.annotations.BeforeMethod; -import org.testng.annotations.Test; - -import com.google.common.collect.ImmutableList; - -public class TestPortSupplierLocation extends BrooklynAppUnitTestSupport { - - SimulatedLocation loc; - PortAttributeSensorAndConfigKey ps; - TestEntity entity; - - @BeforeMethod(alwaysRun=true) - @Override - public void setUp() throws Exception { - super.setUp(); - loc = app.newSimulatedLocation(); - entity = app.createAndManageChild(EntitySpec.create(TestEntity.class)); - app.start(ImmutableList.of(loc)); - - ps = new PortAttributeSensorAndConfigKey("some.port", "for testing", "1234+"); - } - - @Test - public void testObtainsPort() throws Exception { - ConfigToAttributes.apply(entity, ps); - - int p = entity.getAttribute(ps); - assertEquals(p, 1234); - - //sensor access should keep the same value - p = entity.getAttribute(ps); - assertEquals(p, 1234); - } - - @Test - public void testRepeatedConvertAccessIncrements() throws Exception { - int p = ps.getAsSensorValue(entity); - assertEquals(p, 1234); - - //but direct access should see it as being reserved (not required behaviour, but it is the current behaviour) - int p2 = ps.getAsSensorValue(entity); - assertEquals(p2, 1235); - } - - @Test - public void testNullBeforeSetting() throws Exception { - // currently getting the attribute before explicitly setting return null; i.e. no "auto-set" -- - // but this behaviour may be changed - Integer p = entity.getAttribute(ps); - assertEquals(p, null); - } - - @Test - public void testSimulatedRestrictedPermitted() throws Exception { - loc.setPermittedPorts(PortRanges.fromString("1240+")); - - ConfigToAttributes.apply(entity, ps); - int p = entity.getAttribute(ps); - assertEquals((int)p, 1240); - } - -}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a1ad34d7/core/src/test/java/org/apache/brooklyn/location/byon/ByonLocationResolverTest.java ---------------------------------------------------------------------- diff --git a/core/src/test/java/org/apache/brooklyn/location/byon/ByonLocationResolverTest.java b/core/src/test/java/org/apache/brooklyn/location/byon/ByonLocationResolverTest.java new file mode 100644 index 0000000..8d89a40 --- /dev/null +++ b/core/src/test/java/org/apache/brooklyn/location/byon/ByonLocationResolverTest.java @@ -0,0 +1,429 @@ +/* + * 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.byon; + +import static org.testng.Assert.assertEquals; +import static org.testng.Assert.assertTrue; +import static org.testng.Assert.fail; + +import java.net.InetAddress; +import java.util.List; +import java.util.Map; +import java.util.NoSuchElementException; +import java.util.Set; + +import javax.annotation.Nullable; + +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.config.ConfigKeys; +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.apache.brooklyn.location.core.NamedLocationResolver; +import org.apache.brooklyn.location.core.internal.LocationInternal; +import org.apache.brooklyn.location.ssh.SshMachineLocation; +import org.apache.brooklyn.location.winrm.WinRmMachineLocation; +import org.apache.brooklyn.test.Asserts; +import org.apache.brooklyn.util.collections.MutableMap; +import org.apache.brooklyn.util.net.Networking; +import org.apache.brooklyn.util.net.UserAndHostAndPort; +import org.apache.brooklyn.util.os.Os; +import org.apache.brooklyn.util.text.StringPredicates; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.testng.Assert; +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.Joiner; +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.ImmutableSet; +import com.google.common.collect.Iterables; + +public class ByonLocationResolverTest { + + private static final Logger log = LoggerFactory.getLogger(ByonLocationResolverTest.class); + + private BrooklynProperties brooklynProperties; + private LocalManagementContext managementContext; + private Predicate<CharSequence> defaultNamePredicate; + + @BeforeMethod(alwaysRun=true) + public void setUp() throws Exception { + managementContext = LocalManagementContextForTests.newInstance(); + brooklynProperties = managementContext.getBrooklynProperties(); + defaultNamePredicate = StringPredicates.startsWith(FixedListMachineProvisioningLocation.class.getSimpleName()); + } + + @AfterMethod(alwaysRun=true) + public void tearDown() throws Exception { + if (managementContext != null) Entities.destroyAll(managementContext); + } + + @Test + public void testTakesByonScopedProperties() { + brooklynProperties.put("brooklyn.location.byon.privateKeyFile", "myprivatekeyfile"); + brooklynProperties.put("brooklyn.location.byon.publicKeyFile", "mypublickeyfile"); + brooklynProperties.put("brooklyn.location.byon.privateKeyData", "myprivateKeyData"); + brooklynProperties.put("brooklyn.location.byon.publicKeyData", "myPublicKeyData"); + brooklynProperties.put("brooklyn.location.byon.privateKeyPassphrase", "myprivateKeyPassphrase"); + + Map<String, Object> conf = resolve("byon(hosts=\"1.1.1.1\")").config().getBag().getAllConfig(); + + assertEquals(conf.get("privateKeyFile"), "myprivatekeyfile"); + assertEquals(conf.get("publicKeyFile"), "mypublickeyfile"); + assertEquals(conf.get("privateKeyData"), "myprivateKeyData"); + assertEquals(conf.get("publicKeyData"), "myPublicKeyData"); + assertEquals(conf.get("privateKeyPassphrase"), "myprivateKeyPassphrase"); + } + + @Test + public void testNamedByonLocation() throws Exception { + brooklynProperties.put("brooklyn.location.named.mynamed", "byon(hosts=\"1.1.1.1\")"); + + FixedListMachineProvisioningLocation<MachineLocation> loc = resolve("named:mynamed"); + assertEquals(loc.obtain().getAddress(), InetAddress.getByName("1.1.1.1")); + } + + @Test + public void testPropertiesInSpec() throws Exception { + FixedListMachineProvisioningLocation<MachineLocation> loc = resolve("byon(privateKeyFile=myprivatekeyfile,hosts=\"1.1.1.1\")"); + SshMachineLocation machine = (SshMachineLocation)loc.obtain(); + + assertEquals(machine.config().getBag().getStringKey("privateKeyFile"), "myprivatekeyfile"); + assertEquals(machine.getAddress(), Networking.getInetAddressWithFixedName("1.1.1.1")); + } + + @Test + public void testPropertyScopePrecedence() throws Exception { + brooklynProperties.put("brooklyn.location.named.mynamed", "byon(hosts=\"1.1.1.1\")"); + + // prefer those in "named" over everything else + brooklynProperties.put("brooklyn.location.named.mynamed.privateKeyFile", "privateKeyFile-inNamed"); + brooklynProperties.put("brooklyn.location.byon.privateKeyFile", "privateKeyFile-inProviderSpecific"); + brooklynProperties.put("brooklyn.localhost.privateKeyFile", "privateKeyFile-inGeneric"); + + // prefer those in provider-specific over generic + brooklynProperties.put("brooklyn.location.byon.publicKeyFile", "publicKeyFile-inProviderSpecific"); + brooklynProperties.put("brooklyn.location.publicKeyFile", "publicKeyFile-inGeneric"); + + // prefer location-generic if nothing else + brooklynProperties.put("brooklyn.location.privateKeyData", "privateKeyData-inGeneric"); + + Map<String, Object> conf = resolve("named:mynamed").config().getBag().getAllConfig(); + + assertEquals(conf.get("privateKeyFile"), "privateKeyFile-inNamed"); + assertEquals(conf.get("publicKeyFile"), "publicKeyFile-inProviderSpecific"); + assertEquals(conf.get("privateKeyData"), "privateKeyData-inGeneric"); + } + + @Test + public void testThrowsOnInvalid() throws Exception { + assertThrowsNoSuchElement("wrongprefix:(hosts=\"1.1.1.1\")"); + assertThrowsIllegalArgument("byon"); // no hosts + assertThrowsIllegalArgument("byon()"); // no hosts + assertThrowsIllegalArgument("byon(hosts=\"\")"); // empty hosts + assertThrowsIllegalArgument("byon(hosts=\"1.1.1.1\""); // no closing bracket + assertThrowsIllegalArgument("byon(hosts=\"1.1.1.1\", name)"); // no value for name + assertThrowsIllegalArgument("byon(hosts=\"1.1.1.1\", name=)"); // no value for name + } + + @Test(expectedExceptions={IllegalArgumentException.class}) + public void testRegistryCommaResolutionInListNotAllowed() throws NoMachinesAvailableException { + // disallowed since 0.7.0 + // fails because it interprets the entire string as a single byon spec, which does not parse + managementContext.getLocationRegistry().resolve(ImmutableList.of("byon(hosts=\"192.168.0.1\",user=bob),byon(hosts=\"192.168.0.2\",user=bob2)")); + } + + @Test + public void testResolvesHosts() throws Exception { + assertByonClusterEquals(resolve("byon(hosts=\"1.1.1.1\")"), ImmutableSet.of("1.1.1.1")); + assertByonClusterEquals(resolve("byon(hosts=\"1.1.1.1\")"), ImmutableSet.of("1.1.1.1")); + assertByonClusterEquals(resolve("byon(hosts=\"1.1.1.1,1.1.1.2\")"), ImmutableSet.of("1.1.1.1","1.1.1.2")); + assertByonClusterEquals(resolve("byon(hosts=\"1.1.1.1, 1.1.1.2\")"), ImmutableSet.of("1.1.1.1","1.1.1.2")); + } + + @Test + public void testWithOldStyleColon() throws Exception { + assertByonClusterEquals(resolve("byon:(hosts=\"1.1.1.1\")"), ImmutableSet.of("1.1.1.1")); + assertByonClusterEquals(resolve("byon:(hosts=\"1.1.1.1\", name=myname)"), ImmutableSet.of("1.1.1.1"), "myname"); + } + + @Test + public void testUsesDisplayName() throws Exception { + assertByonClusterEquals(resolve("byon(hosts=\"1.1.1.1\", name=myname)"), ImmutableSet.of("1.1.1.1"), "myname"); + assertByonClusterEquals(resolve("byon(hosts=\"1.1.1.1\", name=\"myname\")"), ImmutableSet.of("1.1.1.1"), "myname"); + } + + @Test + public void testResolvesHostsGlobExpansion() throws Exception { + assertByonClusterEquals(resolve("byon(hosts=\"1.1.1.{1,2}\")"), ImmutableSet.of("1.1.1.1","1.1.1.2")); + assertByonClusterEquals(resolve("byon(hosts=\"1.1.{1.1,2.{1,2}}\")"), + ImmutableSet.of("1.1.1.1","1.1.2.1","1.1.2.2")); + assertByonClusterEquals(resolve("byon(hosts=\"1.1.{1,2}.{1,2}\")"), + ImmutableSet.of("1.1.1.1","1.1.1.2","1.1.2.1","1.1.2.2")); + } + + @Test(groups="Integration") + public void testNiceError() throws Exception { + Asserts.assertFailsWith(new Runnable() { + @Override public void run() { + FixedListMachineProvisioningLocation<MachineLocation> x = + resolve("byon(hosts=\"1.1.1.{1,2}}\")"); + log.error("got "+x+" but should have failed (your DNS is giving an IP for hostname '1.1.1.1}' (with the extra '}')"); + } + }, new Predicate<Throwable>() { + @Override + public boolean apply(@Nullable Throwable input) { + String s = input.toString(); + // words + if (!s.contains("Invalid host")) return false; + // problematic entry + if (!s.contains("1.1.1.1}")) return false; + // original spec + if (!s.contains("1.1.1.{1,2}}")) return false; + return true; + } + }); + } + + @Test + public void testResolvesUsernameAtHost() throws Exception { + assertByonClusterWithUsersEquals(resolve("byon(hosts=\"[email protected]\")"), + ImmutableSet.of(UserAndHostAndPort.fromParts("myuser", "1.1.1.1", 22))); + assertByonClusterWithUsersEquals(resolve("byon(hosts=\"[email protected],[email protected]\")"), ImmutableSet.of( + UserAndHostAndPort.fromParts("myuser", "1.1.1.1", 22), UserAndHostAndPort.fromParts("myuser2", "1.1.1.1", 22))); + assertByonClusterWithUsersEquals(resolve("byon(hosts=\"[email protected],[email protected]\")"), ImmutableSet.of( + UserAndHostAndPort.fromParts("myuser", "1.1.1.1", 22), UserAndHostAndPort.fromParts("myuser2", "1.1.1.2", 22))); + } + + @Test + public void testResolvesUserArg() throws Exception { + assertByonClusterWithUsersEquals(resolve("byon(hosts=\"1.1.1.1\",user=bob)"), + ImmutableSet.of(UserAndHostAndPort.fromParts("bob", "1.1.1.1", 22))); + assertByonClusterWithUsersEquals(resolve("byon(user=\"bob\",hosts=\"[email protected],1.1.1.1\")"), + ImmutableSet.of(UserAndHostAndPort.fromParts("myuser", "1.1.1.1", 22), UserAndHostAndPort.fromParts("bob", "1.1.1.1", 22))); + } + + @Test + public void testResolvesUserArg2() throws Exception { + String spec = "byon(hosts=\"1.1.1.1\",user=bob)"; + FixedListMachineProvisioningLocation<MachineLocation> ll = resolve(spec); + SshMachineLocation l = (SshMachineLocation)ll.obtain(); + Assert.assertEquals("bob", l.getUser()); + } + + @SuppressWarnings("unchecked") + @Test + public void testResolvesUserArg3() throws Exception { + String spec = "byon(hosts=\"1.1.1.1\")"; + managementContext.getLocationRegistry().getProperties().putAll(MutableMap.of( + "brooklyn.location.named.foo", spec, + "brooklyn.location.named.foo.user", "bob")); + ((BasicLocationRegistry)managementContext.getLocationRegistry()).updateDefinedLocations(); + + MachineProvisioningLocation<SshMachineLocation> ll = (MachineProvisioningLocation<SshMachineLocation>) + new NamedLocationResolver().newLocationFromString(MutableMap.of(), "named:foo", managementContext.getLocationRegistry()); + SshMachineLocation l = ll.obtain(MutableMap.of()); + Assert.assertEquals("bob", l.getUser()); + } + + @Test + public void testResolvesPortArg() throws Exception { + assertByonClusterWithUsersEquals(resolve("byon(user=bob,port=8022,hosts=\"1.1.1.1\")"), + ImmutableSet.of(UserAndHostAndPort.fromParts("bob", "1.1.1.1", 8022))); + assertByonClusterWithUsersEquals(resolve("byon(user=bob,port=8022,hosts=\"[email protected],1.1.1.2:8901\")"), + ImmutableSet.of(UserAndHostAndPort.fromParts("myuser", "1.1.1.1", 8022), UserAndHostAndPort.fromParts("bob", "1.1.1.2", 8901))); + } + + @SuppressWarnings("unchecked") + @Test + /** private key should be inherited, so confirm that happens correctly */ + public void testResolvesPrivateKeyArgInheritance() throws Exception { + String spec = "byon(hosts=\"1.1.1.1\")"; + managementContext.getLocationRegistry().getProperties().putAll(MutableMap.of( + "brooklyn.location.named.foo", spec, + "brooklyn.location.named.foo.user", "bob", + "brooklyn.location.named.foo.privateKeyFile", "/tmp/x")); + ((BasicLocationRegistry)managementContext.getLocationRegistry()).updateDefinedLocations(); + + MachineProvisioningLocation<SshMachineLocation> ll = (MachineProvisioningLocation<SshMachineLocation>) + new NamedLocationResolver().newLocationFromString(MutableMap.of(), "named:foo", managementContext.getLocationRegistry()); + + Assert.assertEquals("/tmp/x", ll.getConfig(LocationConfigKeys.PRIVATE_KEY_FILE)); + Assert.assertTrue(((LocationInternal)ll).config().getLocalRaw(LocationConfigKeys.PRIVATE_KEY_FILE).isPresent()); + Assert.assertEquals("/tmp/x", ((LocationInternal)ll).config().getLocalBag().getStringKey(LocationConfigKeys.PRIVATE_KEY_FILE.getName())); + Assert.assertEquals("/tmp/x", ((LocationInternal)ll).config().getBag().get(LocationConfigKeys.PRIVATE_KEY_FILE)); + + SshMachineLocation l = ll.obtain(MutableMap.of()); + + Assert.assertEquals("/tmp/x", l.getConfig(LocationConfigKeys.PRIVATE_KEY_FILE)); + + Assert.assertTrue(l.config().getRaw(LocationConfigKeys.PRIVATE_KEY_FILE).isPresent()); + Assert.assertTrue(l.config().getLocalRaw(LocationConfigKeys.PRIVATE_KEY_FILE).isAbsent()); + + Assert.assertEquals("/tmp/x", l.config().getBag().getStringKey(LocationConfigKeys.PRIVATE_KEY_FILE.getName())); + Assert.assertEquals("/tmp/x", l.config().getBag().getStringKey(LocationConfigKeys.PRIVATE_KEY_FILE.getName())); + + Assert.assertEquals("/tmp/x", l.config().getBag().get(LocationConfigKeys.PRIVATE_KEY_FILE)); + } + + @Test + public void testResolvesLocalTempDir() throws Exception { + String localTempDir = Os.mergePaths(Os.tmp(), "testResolvesUsernameAtHost"); + brooklynProperties.put("brooklyn.location.byon.localTempDir", localTempDir); + + FixedListMachineProvisioningLocation<MachineLocation> byon = resolve("byon(hosts=\"1.1.1.1\",osFamily=\"windows\")"); + MachineLocation machine = byon.obtain(); + assertEquals(machine.getConfig(SshMachineLocation.LOCAL_TEMP_DIR), localTempDir); + } + + @Test + public void testMachinesObtainedInOrder() throws Exception { + List<String> ips = ImmutableList.of("1.1.1.1", "1.1.1.6", "1.1.1.3", "1.1.1.4", "1.1.1.5"); + String spec = "byon(hosts=\""+Joiner.on(",").join(ips)+"\")"; + + MachineProvisioningLocation<MachineLocation> ll = resolve(spec); + + for (String expected : ips) { + MachineLocation obtained = ll.obtain(ImmutableMap.of()); + assertEquals(obtained.getAddress().getHostAddress(), expected); + } + } + + @Test + public void testEmptySpec() throws Exception { + String spec = "byon"; + Map<String, ?> flags = ImmutableMap.of( + "hosts", ImmutableList.of("1.1.1.1", "2.2.2.22"), + "name", "foo", + "user", "myuser" + ); + MachineProvisioningLocation<MachineLocation> provisioner = resolve(spec, flags); + SshMachineLocation location1 = (SshMachineLocation)provisioner.obtain(ImmutableMap.of()); + Assert.assertEquals("myuser", location1.getUser()); + Assert.assertEquals("1.1.1.1", location1.getAddress().getHostAddress()); + } + + @Test + public void testWindowsMachines() throws Exception { + brooklynProperties.put("brooklyn.location.byon.user", "myuser"); + brooklynProperties.put("brooklyn.location.byon.password", "mypassword"); + String spec = "byon"; + Map<String, ?> flags = ImmutableMap.of( + "hosts", ImmutableList.of("1.1.1.1", "2.2.2.2"), + "osfamily", "windows" + ); + MachineProvisioningLocation<MachineLocation> provisioner = resolve(spec, flags); + WinRmMachineLocation location = (WinRmMachineLocation) provisioner.obtain(ImmutableMap.of()); + + assertEquals(location.config().get(WinRmMachineLocation.USER), "myuser"); + assertEquals(location.config().get(WinRmMachineLocation.PASSWORD), "mypassword"); + assertEquals(location.config().get(WinRmMachineLocation.ADDRESS).getHostAddress(), "1.1.1.1"); + } + + @Test + public void testNoneWindowsMachines() throws Exception { + String spec = "byon"; + Map<String, ?> flags = ImmutableMap.of( + "hosts", ImmutableList.of("1.1.1.1", "2.2.2.2"), + "osfamily", "linux" + ); + MachineProvisioningLocation<MachineLocation> provisioner = resolve(spec, flags); + MachineLocation location = provisioner.obtain(ImmutableMap.of()); + assertTrue(location instanceof SshMachineLocation, "Expected location to be SshMachineLocation, found " + location); + } + + @Test + public void testAdditionalConfig() throws Exception { + FixedListMachineProvisioningLocation<MachineLocation> loc = resolve("byon(mykey=myval,hosts=\"1.1.1.1\")"); + MachineLocation machine = loc.obtain(ImmutableMap.of()); + assertEquals(machine.getConfig(ConfigKeys.newConfigKey(String.class, "mykey")), "myval"); + } + + private void assertByonClusterEquals(FixedListMachineProvisioningLocation<? extends MachineLocation> cluster, Set<String> expectedHosts) { + assertByonClusterEquals(cluster, expectedHosts, defaultNamePredicate); + } + + private void assertByonClusterEquals(FixedListMachineProvisioningLocation<? extends MachineLocation> cluster, Set<String> expectedHosts, String expectedName) { + assertByonClusterEquals(cluster, expectedHosts, Predicates.equalTo(expectedName)); + } + + private void assertByonClusterEquals(FixedListMachineProvisioningLocation<? extends MachineLocation> cluster, Set<String> expectedHosts, Predicate<? super String> expectedName) { + Set<String> actualHosts = ImmutableSet.copyOf(Iterables.transform(cluster.getMachines(), new Function<MachineLocation, String>() { + @Override public String apply(MachineLocation input) { + return input.getAddress().getHostName(); + }})); + assertEquals(actualHosts, expectedHosts); + assertTrue(expectedName.apply(cluster.getDisplayName()), "name="+cluster.getDisplayName()); + } + + private void assertByonClusterWithUsersEquals(FixedListMachineProvisioningLocation<? extends MachineLocation> cluster, Set<UserAndHostAndPort> expectedHosts) { + assertByonClusterWithUsersEquals(cluster, expectedHosts, defaultNamePredicate); + } + + private void assertByonClusterWithUsersEquals(FixedListMachineProvisioningLocation<? extends MachineLocation> cluster, Set<UserAndHostAndPort> expectedHosts, Predicate<? super String> expectedName) { + Set<UserAndHostAndPort> actualHosts = ImmutableSet.copyOf(Iterables.transform(cluster.getMachines(), new Function<MachineLocation, UserAndHostAndPort>() { + @Override public UserAndHostAndPort apply(MachineLocation input) { + SshMachineLocation machine = (SshMachineLocation) input; + return UserAndHostAndPort.fromParts(machine.getUser(), machine.getAddress().getHostName(), machine.getPort()); + }})); + assertEquals(actualHosts, expectedHosts); + assertTrue(expectedName.apply(cluster.getDisplayName()), "name="+cluster.getDisplayName()); + } + + 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 FixedListMachineProvisioningLocation<MachineLocation> resolve(String val) { + return (FixedListMachineProvisioningLocation<MachineLocation>) managementContext.getLocationRegistry().resolve(val); + } + + @SuppressWarnings("unchecked") + private FixedListMachineProvisioningLocation<MachineLocation> resolve(String val, Map<?, ?> locationFlags) { + return (FixedListMachineProvisioningLocation<MachineLocation>) managementContext.getLocationRegistry().resolve(val, locationFlags); + } +} http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a1ad34d7/core/src/test/java/org/apache/brooklyn/location/byon/FixedListMachineProvisioningLocationRebindTest.java ---------------------------------------------------------------------- diff --git a/core/src/test/java/org/apache/brooklyn/location/byon/FixedListMachineProvisioningLocationRebindTest.java b/core/src/test/java/org/apache/brooklyn/location/byon/FixedListMachineProvisioningLocationRebindTest.java new file mode 100644 index 0000000..3068115 --- /dev/null +++ b/core/src/test/java/org/apache/brooklyn/location/byon/FixedListMachineProvisioningLocationRebindTest.java @@ -0,0 +1,131 @@ +/* + * 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.byon; + +import static org.testng.Assert.assertEquals; + +import java.io.File; +import java.util.Set; + +import javax.annotation.Nullable; + +import org.apache.brooklyn.api.location.Location; +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.core.LocationConfigKeys; +import org.apache.brooklyn.location.ssh.SshMachineLocation; +import org.apache.brooklyn.util.collections.MutableSet; +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.collect.ImmutableList; +import com.google.common.collect.Iterables; + +public class FixedListMachineProvisioningLocationRebindTest { + + private FixedListMachineProvisioningLocation<SshMachineLocation> origLoc; + private ClassLoader classLoader = getClass().getClassLoader(); + private ManagementContext origManagementContext; + private TestApplication origApp; + private TestApplication newApp; + private File mementoDir; + + @BeforeMethod(alwaysRun=true) + public void setUp() throws Exception { + mementoDir = Os.newTempDir(getClass()); + origManagementContext = RebindTestUtils.newPersistingManagementContext(mementoDir, classLoader, 1); + + origLoc = new FixedListMachineProvisioningLocation.Builder(origManagementContext.getLocationManager()) + .addAddresses("localhost", "127.0.0.1") + .user("myuser") + .keyFile("/path/to/myPrivateKeyFile") + .keyData("myKeyData") + .keyPassphrase("myKeyPassphrase") + .build(); + origApp = ApplicationBuilder.newManagedApp(TestApplication.class, origManagementContext); + origApp.start(ImmutableList.of(origLoc)); + } + + @AfterMethod(alwaysRun = true) + public void tearDown() throws Exception { + if (origManagementContext != null) Entities.destroyAll(origManagementContext); + if (newApp != null) Entities.destroyAll(newApp.getManagementContext()); + if (mementoDir != null) RebindTestUtils.deleteMementoDir(mementoDir); + } + + @Test + public void testRebindPreservesConfig() throws Exception { + newApp = rebind(); + FixedListMachineProvisioningLocation<SshMachineLocation> newLoc = (FixedListMachineProvisioningLocation<SshMachineLocation>) Iterables.get(newApp.getLocations(), 0); + + assertEquals(newLoc.getId(), origLoc.getId()); + assertEquals(newLoc.getDisplayName(), origLoc.getDisplayName()); + assertEquals(newLoc.getHostGeoInfo(), origLoc.getHostGeoInfo()); + assertEquals(newLoc.getConfig(LocationConfigKeys.USER), origLoc.getConfig(LocationConfigKeys.USER)); + assertEquals(newLoc.getConfig(LocationConfigKeys.PRIVATE_KEY_PASSPHRASE), origLoc.getConfig(LocationConfigKeys.PRIVATE_KEY_PASSPHRASE)); + assertEquals(newLoc.getConfig(LocationConfigKeys.PRIVATE_KEY_FILE), origLoc.getConfig(LocationConfigKeys.PRIVATE_KEY_FILE)); + assertEquals(newLoc.getConfig(LocationConfigKeys.PRIVATE_KEY_DATA), origLoc.getConfig(LocationConfigKeys.PRIVATE_KEY_DATA)); + } + + @Test + public void testRebindParentRelationship() throws Exception { + newApp = rebind(); + FixedListMachineProvisioningLocation<SshMachineLocation> newLoc = (FixedListMachineProvisioningLocation<SshMachineLocation>) Iterables.get(newApp.getLocations(), 0); + + assertLocationIdsEqual(newLoc.getChildren(), origLoc.getChildren()); + assertEquals(Iterables.get(newLoc.getChildren(), 0).getParent(), newLoc); + assertEquals(Iterables.get(newLoc.getChildren(), 1).getParent(), newLoc); + } + + @Test + public void testRebindPreservesInUseMachines() throws Exception { + SshMachineLocation inuseMachine = origLoc.obtain(); + origApp.setAttribute(TestApplication.SERVICE_UP, true); // to force persist, and thus avoid race + + newApp = rebind(); + FixedListMachineProvisioningLocation<SshMachineLocation> newLoc = (FixedListMachineProvisioningLocation<SshMachineLocation>) Iterables.get(newApp.getLocations(), 0); + + assertLocationIdsEqual(newLoc.getInUse(), origLoc.getInUse()); + assertLocationIdsEqual(newLoc.getAvailable(), origLoc.getAvailable()); + } + + private TestApplication rebind() throws Exception { + RebindTestUtils.waitForPersisted(origApp); + return (TestApplication) RebindTestUtils.rebind(mementoDir, getClass().getClassLoader()); + } + + private void assertLocationIdsEqual(Iterable<? extends Location> actual, Iterable<? extends Location> expected) { + Function<Location, String> locationIdFunction = new Function<Location, String>() { + @Override public String apply(@Nullable Location input) { + return (input != null) ? input.getId() : null; + } + }; + Set<String> actualIds = MutableSet.copyOf(Iterables.transform(actual, locationIdFunction)); + Set<String> expectedIds = MutableSet.copyOf(Iterables.transform(expected, locationIdFunction)); + + assertEquals(actualIds, expectedIds); + } +} http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a1ad34d7/core/src/test/java/org/apache/brooklyn/location/byon/FixedListMachineProvisioningLocationTest.java ---------------------------------------------------------------------- diff --git a/core/src/test/java/org/apache/brooklyn/location/byon/FixedListMachineProvisioningLocationTest.java b/core/src/test/java/org/apache/brooklyn/location/byon/FixedListMachineProvisioningLocationTest.java new file mode 100644 index 0000000..f36ab1e --- /dev/null +++ b/core/src/test/java/org/apache/brooklyn/location/byon/FixedListMachineProvisioningLocationTest.java @@ -0,0 +1,578 @@ +/* + * 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.byon; + +import static org.testng.Assert.assertEquals; +import static org.testng.Assert.assertFalse; +import static org.testng.Assert.fail; + +import java.net.Inet4Address; +import java.net.UnknownHostException; +import java.util.List; +import java.util.Random; +import java.util.concurrent.atomic.AtomicInteger; + +import org.apache.brooklyn.api.location.LocationSpec; +import org.apache.brooklyn.api.location.MachineLocation; +import org.apache.brooklyn.api.location.NoMachinesAvailableException; +import org.apache.brooklyn.config.ConfigKey; +import org.apache.brooklyn.core.config.ConfigKeys; +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.RecordingMachineLocationCustomizer; +import org.apache.brooklyn.location.core.RecordingMachineLocationCustomizer.Call; +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.net.Networking; +import org.apache.brooklyn.util.stream.Streams; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.testng.Assert; +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.collect.ImmutableList; +import com.google.common.collect.ImmutableMap; +import com.google.common.collect.ImmutableSet; +import com.google.common.collect.Iterables; +import com.google.common.collect.Lists; + +/** + * Provisions {@link SshMachineLocation}s in a specific location from a list of known machines + */ +public class FixedListMachineProvisioningLocationTest { + + private static final Logger LOG = LoggerFactory.getLogger(FixedListMachineProvisioningLocationTest.class); + + SshMachineLocation machine; + LocalManagementContext mgmt; + FixedListMachineProvisioningLocation<SshMachineLocation> provisioner; + FixedListMachineProvisioningLocation<SshMachineLocation> provisioner2; + + @SuppressWarnings("unchecked") + @BeforeMethod(alwaysRun=true) + public void createProvisioner() throws UnknownHostException { + mgmt = LocalManagementContextForTests.newInstance(); + + machine = mgmt.getLocationManager().createLocation(MutableMap.of("address", Inet4Address.getByName("192.168.144.200")), SshMachineLocation.class); + provisioner = mgmt.getLocationManager().createLocation( + MutableMap.of("machines", MutableList.of(machine)), + FixedListMachineProvisioningLocation.class); + } + + @AfterMethod(alwaysRun=true) + public void tearDown() throws Exception { + if (provisioner != null) Streams.closeQuietly(provisioner); + if (provisioner2 != null) Streams.closeQuietly(provisioner2); + Entities.destroyAll(mgmt); + } + + @Test + public void testSetsChildLocations() throws NoMachinesAvailableException { + // Available machines should be listed as children + assertEquals(ImmutableList.copyOf(provisioner.getChildren()), ImmutableList.of(machine)); + + // In-use machines should also be listed as children + provisioner.obtain(); + assertEquals(ImmutableList.copyOf(provisioner.getChildren()), ImmutableList.of(machine)); + } + + @Test + public void canObtainMachine() throws NoMachinesAvailableException { + SshMachineLocation obtained = provisioner.obtain(); + assertEquals(obtained, machine); + } + + @SuppressWarnings("unused") + @Test(expectedExceptions = { NoMachinesAvailableException.class }) + public void throwsExceptionIfNoMachinesAvailable() throws NoMachinesAvailableException { + SshMachineLocation machine1 = provisioner.obtain(); + SshMachineLocation machine2 = provisioner.obtain(); + fail("Did not throw NoMachinesAvailableException as expected"); + } + + @Test + public void canGetAMachineReturnItAndObtainItAgain() throws NoMachinesAvailableException { + SshMachineLocation obtained = provisioner.obtain(); + provisioner.release(obtained); + SshMachineLocation obtained2 = provisioner.obtain(); + assertEquals(obtained2, machine); + } + + @Test + public void theBuilder() throws NoMachinesAvailableException { + provisioner2 = + new FixedListMachineProvisioningLocation.Builder(mgmt.getLocationManager()). + user("u1"). + addAddress("192.168.0.1"). + addAddress("[email protected]"). + addAddress("192.168.0.{3,4}"). + addAddresses("192.168.0.{6-8}"). + addAddressMultipleTimes("192.168.0.{8,7}", 2). + addAddress("[email protected].{11-20}"). + build(); + assertUserAndHost(provisioner2.obtain(), "u1", "192.168.0.1"); + assertUserAndHost(provisioner2.obtain(), "u2", "192.168.0.2"); + for (int i=3; i<=4; i++) assertUserAndHost(provisioner2.obtain(), "u1", "192.168.0."+i); + for (int i=6; i<=8; i++) assertUserAndHost(provisioner2.obtain(), "u1", "192.168.0."+i); + for (int j=0; j<2; j++) + for (int i=8; i>=7; i--) assertUserAndHost(provisioner2.obtain(), "u1", "192.168.0."+i); + for (int i=11; i<=20; i++) assertUserAndHost(provisioner2.obtain(), "u3", "192.168.0."+i); + try { + provisioner2.obtain(); + fail("Should not have obtained"); //throws error so not caught below + } catch (Exception e) { + /** expected */ + } + } + + @Test + public void theBuilderLegacy() throws NoMachinesAvailableException { + provisioner2 = + new FixedListMachineProvisioningLocation.Builder(mgmt.getLocationManager()). + user("u1"). + addAddress("192.168.0.1"). + addAddress("[email protected]"). + addAddress("192.168.0.{3,4}"). + addAddresses("192.168.0.{6-8}"). + addAddressMultipleTimes("192.168.0.{8,7}", 2). + addAddress("[email protected].{11-20}"). + build(); + assertUserAndHost(provisioner2.obtain(), "u1", "192.168.0.1"); + assertUserAndHost(provisioner2.obtain(), "u2", "192.168.0.2"); + for (int i=3; i<=4; i++) assertUserAndHost(provisioner2.obtain(), "u1", "192.168.0."+i); + for (int i=6; i<=8; i++) assertUserAndHost(provisioner2.obtain(), "u1", "192.168.0."+i); + for (int j=0; j<2; j++) + for (int i=8; i>=7; i--) assertUserAndHost(provisioner2.obtain(), "u1", "192.168.0."+i); + for (int i=11; i<=20; i++) assertUserAndHost(provisioner2.obtain(), "u3", "192.168.0."+i); + try { + provisioner2.obtain(); + fail("Should not have obtained"); //throws error so not caught below + } catch (Exception e) { + /** expected */ + } + } + + @Test(expectedExceptions = { IllegalStateException.class }) + public void throwsExceptionIfTryingToReleaseUnallocationMachine() throws NoMachinesAvailableException, UnknownHostException { + @SuppressWarnings("unused") + SshMachineLocation obtained = provisioner.obtain(); + provisioner.release(new SshMachineLocation(MutableMap.of("address", Inet4Address.getByName("192.168.144.201")))); + fail("Did not throw IllegalStateException as expected"); + } + + @Test + public void testCanAddMachineToPool() throws UnknownHostException, NoMachinesAvailableException { + SshMachineLocation machine2 = new SshMachineLocation( + MutableMap.of("address", Inet4Address.getByName("192.168.144.200"))); + provisioner2 = new FixedListMachineProvisioningLocation<SshMachineLocation>( + MutableMap.of("machines", MutableList.of())); + provisioner2.addMachine(machine2); + + assertEquals(ImmutableList.copyOf(provisioner2.getChildren()), ImmutableList.of(machine2)); + assertEquals(ImmutableSet.copyOf(provisioner2.getAvailable()), ImmutableSet.of(machine2)); + + SshMachineLocation obtained = provisioner2.obtain(); + assertEquals(obtained, machine2); + + // Can only obtain the added machien once though (i.e. not added multiple times somehow) + try { + SshMachineLocation obtained2 = provisioner2.obtain(); + fail("obtained="+obtained2); + } catch (NoMachinesAvailableException e) { + // success + } + } + + @Test + public void testCanRemoveAvailableMachineFromPool() { + provisioner.removeMachine(machine); + + Assert.assertTrue(provisioner.getChildren().isEmpty()); + Assert.assertTrue(provisioner.getAvailable().isEmpty()); + + try { + SshMachineLocation obtained = provisioner.obtain(); + fail("obtained="+obtained); + } catch (NoMachinesAvailableException e) { + // success + } + } + + @Test + public void testCanRemoveObtainedMachineFromPoolSoNotReallocated() throws NoMachinesAvailableException { + SshMachineLocation obtained = provisioner.obtain(); + provisioner.removeMachine(obtained); + + // Continue to know about the machine until it is returned + assertEquals(ImmutableList.copyOf(provisioner.getChildren()), ImmutableList.of(machine)); + Assert.assertTrue(provisioner.getAvailable().isEmpty()); + + // When released, the machine is then removed entirely + provisioner.release(obtained); + + Assert.assertTrue(provisioner.getChildren().isEmpty()); + Assert.assertTrue(provisioner.getAvailable().isEmpty()); + + // So no machines left; cannot re-obtain + try { + SshMachineLocation obtained2 = provisioner.obtain(); + fail("obtained="+obtained2); + } catch (NoMachinesAvailableException e) { + // success + } + } + + @Test + public void testObtainDesiredMachineThrowsIfNotKnown() throws Exception { + SshMachineLocation machine2 = new SshMachineLocation( + MutableMap.of("address", Inet4Address.getByName("192.168.144.201"))); + try { + SshMachineLocation obtained = provisioner.obtain(MutableMap.of("desiredMachine", machine2)); + fail("obtained="+obtained); + } catch (IllegalStateException e) { + if (!e.toString().contains("machine unknown")) throw e; + } + } + + @Test + public void testObtainDesiredMachineThrowsIfInUse() throws Exception { + provisioner.addMachine(new SshMachineLocation( + MutableMap.of("address", Inet4Address.getByName("192.168.144.201")))); + SshMachineLocation obtained = provisioner.obtain(); + try { + SshMachineLocation obtained2 = provisioner.obtain(MutableMap.of("desiredMachine", obtained)); + fail("obtained2="+obtained2); + } catch (IllegalStateException e) { + if (!e.toString().contains("machine in use")) throw e; + } + } + + @Test + public void testObtainDesiredMachineReturnsDesired() throws Exception { + int desiredMachineIndex = 10; + SshMachineLocation desiredMachine = null; + for (int i = 0; i < 20; i++) { + SshMachineLocation newMachine = new SshMachineLocation( + MutableMap.of("address", Inet4Address.getByName("192.168.144."+(201+i)))); + if (i == desiredMachineIndex) desiredMachine = newMachine; + provisioner.addMachine(newMachine); + } + SshMachineLocation obtained = provisioner.obtain(MutableMap.of("desiredMachine", desiredMachine)); + assertEquals(obtained, desiredMachine); + } + + @Test + public void testAddAndRemoveChildUpdatesMachinesSet() throws Exception { + SshMachineLocation anotherMachine = new SshMachineLocation( + MutableMap.of("address", Inet4Address.getByName("192.168.144.201"))); + provisioner.addChild(anotherMachine); + assertEquals(provisioner.getAllMachines(), ImmutableSet.of(machine, anotherMachine)); + + provisioner.removeChild(anotherMachine); + assertEquals(provisioner.getAllMachines(), ImmutableSet.of(machine)); + } + + @Test + public void testCanAddAlreadyParentedMachine() throws UnknownHostException, NoMachinesAvailableException { + provisioner.obtain(); // so no machines left + + FixedListMachineProvisioningLocation<SshMachineLocation> provisioner2 = new FixedListMachineProvisioningLocation.Builder(mgmt.getLocationManager()) + .addAddress("1.2.3.4") + .build(); + SshMachineLocation machine = provisioner2.obtain(); + + provisioner.addMachine(machine); + assertEquals(provisioner.obtain(), machine); + } + + @Test + public void testCanCreateWithAlreadyParentedMachine() throws UnknownHostException, NoMachinesAvailableException { + machine = provisioner.obtain(); + + FixedListMachineProvisioningLocation<SshMachineLocation> provisioner2 = new FixedListMachineProvisioningLocation.Builder(mgmt.getLocationManager()) + .add(machine) + .build(); + assertEquals(provisioner2.obtain(), machine); + } + + @Test + @SuppressWarnings("unchecked") + public void testMachinesObtainedInOrder() throws Exception { + List<SshMachineLocation> machines = ImmutableList.of( + mgmt.getLocationManager().createLocation(LocationSpec.create(SshMachineLocation.class).configure("address", Networking.getInetAddressWithFixedName("1.1.1.1"))), + mgmt.getLocationManager().createLocation(LocationSpec.create(SshMachineLocation.class).configure("address", Networking.getInetAddressWithFixedName("1.1.1.6"))), + mgmt.getLocationManager().createLocation(LocationSpec.create(SshMachineLocation.class).configure("address", Networking.getInetAddressWithFixedName("1.1.1.3"))), + mgmt.getLocationManager().createLocation(LocationSpec.create(SshMachineLocation.class).configure("address", Networking.getInetAddressWithFixedName("1.1.1.4"))), + mgmt.getLocationManager().createLocation(LocationSpec.create(SshMachineLocation.class).configure("address", Networking.getInetAddressWithFixedName("1.1.1.5")))); + + provisioner2 = mgmt.getLocationManager().createLocation( + MutableMap.of("machines", machines), + FixedListMachineProvisioningLocation.class); + + for (SshMachineLocation expected : machines) { + assertEquals(provisioner2.obtain(), expected); + } + } + + @Test + @SuppressWarnings("unchecked") + public void testMachineChooser() throws Exception { + List<SshMachineLocation> machines = Lists.newArrayList(); + for (int i = 0; i < 10; i++) { + machines.add(mgmt.getLocationManager().createLocation(LocationSpec.create(SshMachineLocation.class).configure("address", Networking.getInetAddressWithFixedName("1.1.1."+i)))); + } + final List<SshMachineLocation> desiredOrder = randomized(machines); + + Function<Iterable<? extends MachineLocation>, MachineLocation> chooser = new Function<Iterable<? extends MachineLocation>, MachineLocation>() { + @Override public MachineLocation apply(Iterable<? extends MachineLocation> input) { + for (SshMachineLocation contender : desiredOrder) { + if (Iterables.contains(input, contender)) { + return contender; + } + } + Assert.fail("No intersection of input="+input+" and desiredOrder="+desiredOrder); + return null; // unreachable code + } + }; + provisioner2 = mgmt.getLocationManager().createLocation(LocationSpec.create(FixedListMachineProvisioningLocation.class) + .configure("machines", machines) + .configure(FixedListMachineProvisioningLocation.MACHINE_CHOOSER, chooser)); + + List<SshMachineLocation> result = Lists.newArrayList(); + for (int i = 0; i < machines.size(); i++) { + result.add(provisioner2.obtain()); + } + assertEquals(result, desiredOrder, "result="+result+"; desired="+desiredOrder); + LOG.debug("chooser's desiredOrder="+desiredOrder); + } + + @Test + @SuppressWarnings("unchecked") + public void testMachineChooserPassedToObtain() throws Exception { + List<SshMachineLocation> machines = Lists.newArrayList(); + for (int i = 0; i < 10; i++) { + machines.add(mgmt.getLocationManager().createLocation(LocationSpec.create(SshMachineLocation.class).configure("address", Networking.getInetAddressWithFixedName("1.1.1."+i)))); + } + final List<SshMachineLocation> desiredOrder = randomized(machines); + + Function<Iterable<? extends MachineLocation>, MachineLocation> chooser = new Function<Iterable<? extends MachineLocation>, MachineLocation>() { + @Override public MachineLocation apply(Iterable<? extends MachineLocation> input) { + for (SshMachineLocation contender : desiredOrder) { + if (Iterables.contains(input, contender)) { + return contender; + } + } + Assert.fail("No intersection of input="+input+" and desiredOrder="+desiredOrder); + return null; // unreachable code + } + }; + provisioner2 = mgmt.getLocationManager().createLocation(LocationSpec.create(FixedListMachineProvisioningLocation.class) + .configure("machines", machines)); + + List<SshMachineLocation> result = Lists.newArrayList(); + for (int i = 0; i < machines.size(); i++) { + result.add(provisioner2.obtain(ImmutableMap.of(FixedListMachineProvisioningLocation.MACHINE_CHOOSER, chooser))); + } + assertEquals(result, desiredOrder, "result="+result+"; desired="+desiredOrder); + LOG.debug("chooser's desiredOrder="+desiredOrder); + } + + @Test + @SuppressWarnings("unchecked") + public void testMachineChooserNotCalledWhenNoMachines() throws Exception { + List<SshMachineLocation> machines = ImmutableList.of( + mgmt.getLocationManager().createLocation(LocationSpec.create(SshMachineLocation.class).configure("address", Networking.getInetAddressWithFixedName("1.1.1.1")))); + final AtomicInteger callCount = new AtomicInteger(); + + Function<Iterable<? extends MachineLocation>, MachineLocation> chooser = new Function<Iterable<? extends MachineLocation>, MachineLocation>() { + @Override public MachineLocation apply(Iterable<? extends MachineLocation> input) { + callCount.incrementAndGet(); + return Iterables.get(input, 0); + } + }; + provisioner2 = mgmt.getLocationManager().createLocation(LocationSpec.create(FixedListMachineProvisioningLocation.class) + .configure("machines", machines) + .configure(FixedListMachineProvisioningLocation.MACHINE_CHOOSER, chooser)); + provisioner2.obtain(); + + // When no machines available should fail gracefully, without asking the "chooser" + try { + provisioner2.obtain(); + fail("Expected "+NoMachinesAvailableException.class.getSimpleName()); + } catch (NoMachinesAvailableException e) { + // Pass; sensible exception + } + assertEquals(callCount.get(), 1); + } + + @Test + @SuppressWarnings("unchecked") + public void testFailsWhenMachineChooserReturnsAlreadyAllocatedMachine() throws Exception { + final SshMachineLocation machine1 = mgmt.getLocationManager().createLocation(LocationSpec.create(SshMachineLocation.class).configure("address", Networking.getInetAddressWithFixedName("1.1.1.1"))); + final SshMachineLocation machine2 = mgmt.getLocationManager().createLocation(LocationSpec.create(SshMachineLocation.class).configure("address", Networking.getInetAddressWithFixedName("1.1.1.2"))); + List<SshMachineLocation> machines = ImmutableList.of(machine1, machine2); + + Function<Iterable<? extends MachineLocation>, MachineLocation> chooser = new Function<Iterable<? extends MachineLocation>, MachineLocation>() { + @Override public MachineLocation apply(Iterable<? extends MachineLocation> input) { + return machine1; + } + }; + provisioner2 = mgmt.getLocationManager().createLocation(LocationSpec.create(FixedListMachineProvisioningLocation.class) + .configure("machines", machines) + .configure(FixedListMachineProvisioningLocation.MACHINE_CHOOSER, chooser)); + provisioner2.obtain(); + + // Should fail when tries to return same machine for a second time + try { + provisioner2.obtain(); + fail("Expected "+IllegalStateException.class.getSimpleName()); + } catch (IllegalStateException e) { + if (!e.toString().contains("Machine chooser attempted to choose ")) throw e; + } + } + + @Test + @SuppressWarnings("unchecked") + public void testFailsWhenMachineChooserReturnsInvalidMachine() throws Exception { + final SshMachineLocation machine1 = mgmt.getLocationManager().createLocation(LocationSpec.create(SshMachineLocation.class).configure("address", Networking.getInetAddressWithFixedName("1.1.1.1"))); + final SshMachineLocation machineOther = mgmt.getLocationManager().createLocation(LocationSpec.create(SshMachineLocation.class).configure("address", Networking.getInetAddressWithFixedName("2.2.2.1"))); + List<SshMachineLocation> machines = ImmutableList.of(machine1); + + Function<Iterable<? extends MachineLocation>, MachineLocation> chooser = new Function<Iterable<? extends MachineLocation>, MachineLocation>() { + @Override public MachineLocation apply(Iterable<? extends MachineLocation> input) { + return machineOther; + } + }; + provisioner2 = mgmt.getLocationManager().createLocation(LocationSpec.create(FixedListMachineProvisioningLocation.class) + .configure("machines", machines) + .configure(FixedListMachineProvisioningLocation.MACHINE_CHOOSER, chooser)); + + // Call when no machines available should fail gracefully, without asking the "chooser" + try { + provisioner2.obtain(); + fail("Expected "+IllegalStateException.class.getSimpleName()); + } catch (IllegalStateException e) { + if (!e.toString().contains("Machine chooser attempted to choose ")) throw e; + } + } + + @Test + @SuppressWarnings("unchecked") + public void testMachineCustomizerSetOnByon() throws Exception { + machine = mgmt.getLocationManager().createLocation(MutableMap.of("address", Inet4Address.getByName("192.168.144.200")), SshMachineLocation.class); + RecordingMachineLocationCustomizer customizer = new RecordingMachineLocationCustomizer(); + + provisioner2 = mgmt.getLocationManager().createLocation(LocationSpec.create(FixedListMachineProvisioningLocation.class) + .configure("machines", ImmutableList.of(machine)) + .configure(FixedListMachineProvisioningLocation.MACHINE_LOCATION_CUSTOMIZERS.getName(), ImmutableList.of(customizer))); + + SshMachineLocation obtained = provisioner2.obtain(); + Assert.assertEquals(Iterables.getOnlyElement(customizer.calls), new RecordingMachineLocationCustomizer.Call("customize", ImmutableList.of(obtained))); + + provisioner2.release(obtained); + assertEquals(customizer.calls.size(), 2); + Assert.assertEquals(Iterables.get(customizer.calls, 1), new RecordingMachineLocationCustomizer.Call("preRelease", ImmutableList.of(obtained))); + } + + @Test + public void testMachineCustomizerSetOnObtainCall() throws Exception { + RecordingMachineLocationCustomizer customizer = new RecordingMachineLocationCustomizer(); + + SshMachineLocation obtained = provisioner.obtain(ImmutableMap.of(FixedListMachineProvisioningLocation.MACHINE_LOCATION_CUSTOMIZERS, ImmutableList.of(customizer))); + Assert.assertEquals(Iterables.getOnlyElement(customizer.calls), new RecordingMachineLocationCustomizer.Call("customize", ImmutableList.of(obtained))); + + provisioner.release(obtained); + assertEquals(customizer.calls.size(), 2); + Assert.assertEquals(customizer.calls.get(1), new RecordingMachineLocationCustomizer.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) { + // TODO inefficient implementation, but don't care for small tests + Random random = new Random(); + List<T> result = Lists.newLinkedList(); + for (T element : list) { + int index = (result.isEmpty() ? 0 : random.nextInt(result.size())); + result.add(index, element); + } + return result; + } + + private static void assertUserAndHost(SshMachineLocation l, String user, String host) { + assertEquals(l.getUser(), user); + assertEquals(l.getAddress().getHostAddress(), host); + } +} http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a1ad34d7/core/src/test/java/org/apache/brooklyn/location/byon/HostLocationResolverTest.java ---------------------------------------------------------------------- diff --git a/core/src/test/java/org/apache/brooklyn/location/byon/HostLocationResolverTest.java b/core/src/test/java/org/apache/brooklyn/location/byon/HostLocationResolverTest.java new file mode 100644 index 0000000..24427f6 --- /dev/null +++ b/core/src/test/java/org/apache/brooklyn/location/byon/HostLocationResolverTest.java @@ -0,0 +1,126 @@ +/* + * 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.byon; + +import static org.testng.Assert.assertEquals; +import static org.testng.Assert.fail; + +import java.net.InetAddress; +import java.util.Map; +import java.util.NoSuchElementException; + +import org.apache.brooklyn.api.location.MachineProvisioningLocation; +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.ssh.SshMachineLocation; +import org.testng.annotations.AfterMethod; +import org.testng.annotations.BeforeMethod; +import org.testng.annotations.Test; + +import com.google.common.collect.ImmutableMap; + +public class HostLocationResolverTest { + + 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("host"); + } + + @Test + public void testThrowsOnInvalidTarget() throws Exception { + assertThrowsIllegalArgument("host:()"); + } + + @Test + public void resolveHosts() { + resolve("host:(\"1.1.1.1\")"); + resolve("host:(\"localhost\")"); + } + + @Test(groups="Integration") + public void resolveRealHosts() { + // must be online to resolve this + resolve("host:(\"www.foo.com\")"); + } + + @Test + public void testNamedByonLocation() throws Exception { + brooklynProperties.put("brooklyn.location.named.mynamed", "host:(\"1.1.1.1\")"); + + MachineProvisioningLocation<SshMachineLocation> loc = resolve("named:mynamed"); + assertEquals(loc.obtain(ImmutableMap.of()).getAddress(), InetAddress.getByName("1.1.1.1")); + } + + @Test + public void testPropertyScopePrescedence() throws Exception { + brooklynProperties.put("brooklyn.location.named.mynamed", "host:(\"1.1.1.1\")"); + + // prefer those in "named" over everything else + brooklynProperties.put("brooklyn.location.named.mynamed.privateKeyFile", "privateKeyFile-inNamed"); + brooklynProperties.put("brooklyn.localhost.privateKeyFile", "privateKeyFile-inGeneric"); + + // prefer location-generic if nothing else + brooklynProperties.put("brooklyn.location.privateKeyData", "privateKeyData-inGeneric"); + + Map<String, Object> conf = resolve("named:mynamed").obtain(ImmutableMap.of()).config().getBag().getAllConfig(); + + assertEquals(conf.get("privateKeyFile"), "privateKeyFile-inNamed"); + assertEquals(conf.get("privateKeyData"), "privateKeyData-inGeneric"); + } + + 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 MachineProvisioningLocation<SshMachineLocation> resolve(String val) { + return (MachineProvisioningLocation<SshMachineLocation>) managementContext.getLocationRegistry().resolve(val); + } +} http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a1ad34d7/core/src/test/java/org/apache/brooklyn/location/byon/SingleMachineLocationResolverTest.java ---------------------------------------------------------------------- diff --git a/core/src/test/java/org/apache/brooklyn/location/byon/SingleMachineLocationResolverTest.java b/core/src/test/java/org/apache/brooklyn/location/byon/SingleMachineLocationResolverTest.java new file mode 100644 index 0000000..8fbca63 --- /dev/null +++ b/core/src/test/java/org/apache/brooklyn/location/byon/SingleMachineLocationResolverTest.java @@ -0,0 +1,132 @@ +/* + * 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.byon; + +import static org.testng.Assert.assertEquals; +import static org.testng.Assert.fail; + +import java.net.InetAddress; +import java.util.Map; +import java.util.NoSuchElementException; + +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.SingleMachineProvisioningLocation; +import org.apache.brooklyn.location.ssh.SshMachineLocation; +import org.testng.annotations.AfterMethod; +import org.testng.annotations.BeforeMethod; +import org.testng.annotations.Test; + +import com.google.common.collect.ImmutableMap; + +public class SingleMachineLocationResolverTest { + + 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("single()"); + assertThrowsIllegalArgument("single(wrongprefix:(hosts=\"1.1.1.1\"))"); + assertThrowsIllegalArgument("single(foo:bar)"); + } + + @Test + public void resolveHosts() { + resolve("single(target=localhost)"); + resolve("single(target=byon(hosts=\"1.1.1.1\"))"); + + brooklynProperties.put("brooklyn.location.named.mynamed", "single(target=byon:(hosts=\"1.1.1.1\"))"); + managementContext.clearLocationRegistry(); + resolve("single(target=named:mynamed)"); + } + + @Test + public void resolveWithOldColonFormat() { + resolve("single:(target=localhost)"); + } + + @Test + public void testNamedByonLocation() throws Exception { + brooklynProperties.put("brooklyn.location.named.mynamed", "single(target=byon:(hosts=\"1.1.1.1\"))"); + + SingleMachineProvisioningLocation<SshMachineLocation> loc = resolve("named:mynamed"); + assertEquals(loc.obtain(ImmutableMap.of()).getAddress(), InetAddress.getByName("1.1.1.1")); + } + + @Test + public void testPropertyScopePrescedence() throws Exception { + brooklynProperties.put("brooklyn.location.named.mynamed", "single(target=byon:(hosts=\"1.1.1.1\"))"); + + // prefer those in "named" over everything else + brooklynProperties.put("brooklyn.location.named.mynamed.privateKeyFile", "privateKeyFile-inNamed"); + brooklynProperties.put("brooklyn.localhost.privateKeyFile", "privateKeyFile-inGeneric"); + + // prefer location-generic if nothing else + brooklynProperties.put("brooklyn.location.privateKeyData", "privateKeyData-inGeneric"); + + Map<String, Object> conf = resolve("named:mynamed").obtain(ImmutableMap.of()).config().getBag().getAllConfig(); + + assertEquals(conf.get("privateKeyFile"), "privateKeyFile-inNamed"); + assertEquals(conf.get("privateKeyData"), "privateKeyData-inGeneric"); + } + + 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 SingleMachineProvisioningLocation<SshMachineLocation> resolve(String val) { + return (SingleMachineProvisioningLocation<SshMachineLocation>) managementContext.getLocationRegistry().resolve(val); + } + +} http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a1ad34d7/core/src/test/java/org/apache/brooklyn/location/byon/SingleMachineProvisioningLocationTest.java ---------------------------------------------------------------------- diff --git a/core/src/test/java/org/apache/brooklyn/location/byon/SingleMachineProvisioningLocationTest.java b/core/src/test/java/org/apache/brooklyn/location/byon/SingleMachineProvisioningLocationTest.java new file mode 100644 index 0000000..27dee20 --- /dev/null +++ b/core/src/test/java/org/apache/brooklyn/location/byon/SingleMachineProvisioningLocationTest.java @@ -0,0 +1,65 @@ +/* + * 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.byon; + +import static org.testng.Assert.assertNotNull; + +import org.apache.brooklyn.core.mgmt.internal.LocalManagementContext; +import org.apache.brooklyn.core.test.entity.LocalManagementContextForTests; +import org.apache.brooklyn.location.byon.SingleMachineProvisioningLocation; +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 SingleMachineProvisioningLocationTest { + + private static final Logger log = LoggerFactory.getLogger(SingleMachineProvisioningLocation.class); + + private LocalManagementContext managementContext; + + @BeforeMethod(alwaysRun=true) + public void setUp() throws Exception { + managementContext = LocalManagementContextForTests.newInstance(); + } + + @AfterMethod(alwaysRun=true) + public void tearDown() throws Exception { + if (managementContext != null) managementContext.terminate(); + } + + @SuppressWarnings("unchecked") + @Test + public void testLocalhostSingle() throws Exception { + SingleMachineProvisioningLocation<SshMachineLocation> l = (SingleMachineProvisioningLocation<SshMachineLocation>) + managementContext.getLocationRegistry().resolve("single:(target='localhost')"); + l.setManagementContext(managementContext); + + SshMachineLocation m1 = l.obtain(); + + assertNotNull(m1); + + log.info("GOT "+m1); + + l.release(m1); + } + +} http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a1ad34d7/core/src/test/java/org/apache/brooklyn/location/core/AbstractLocationTest.java ---------------------------------------------------------------------- diff --git a/core/src/test/java/org/apache/brooklyn/location/core/AbstractLocationTest.java b/core/src/test/java/org/apache/brooklyn/location/core/AbstractLocationTest.java new file mode 100644 index 0000000..eb9c906 --- /dev/null +++ b/core/src/test/java/org/apache/brooklyn/location/core/AbstractLocationTest.java @@ -0,0 +1,185 @@ +/* + * 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.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.apache.brooklyn.location.core.internal.LocationInternal; +import org.apache.brooklyn.util.collections.MutableMap; +import org.apache.brooklyn.util.collections.MutableSet; +import org.apache.brooklyn.util.core.flags.SetFromFlag; +import org.testng.annotations.AfterMethod; +import org.testng.annotations.BeforeMethod; +import org.testng.annotations.Test; + +import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableMap; + +public class AbstractLocationTest { + + public static class ConcreteLocation extends AbstractLocation { + private static final long serialVersionUID = 3954199300889119970L; + @SetFromFlag(defaultVal="mydefault") + String myfield; + + public ConcreteLocation() { + super(); + } + + public ConcreteLocation(Map<?,?> properties) { + super(properties); + } + } + + private ManagementContext mgmt; + + @BeforeMethod(alwaysRun=true) + public void setUp() throws Exception { + mgmt = LocalManagementContextForTests.newInstance(); + } + + @AfterMethod(alwaysRun = true) + public void tearDown(){ + if (mgmt!=null) Entities.destroyAll(mgmt); + } + + private ConcreteLocation createConcrete() { + return createConcrete(MutableMap.<String,Object>of()); + } + private ConcreteLocation createConcrete(Map<String,?> flags) { + return createConcrete(null, flags); + } + @SuppressWarnings("deprecation") + private ConcreteLocation createConcrete(String id, Map<String,?> flags) { + return mgmt.getLocationManager().createLocation( LocationSpec.create(ConcreteLocation.class).id(id).configure(flags) ); + } + + @Test + public void testEqualsUsesId() { + Location l1 = createConcrete("1", MutableMap.of("name", "bob")); + Location l1b = new ConcreteLocation(ImmutableMap.of("id", 1)); + Location l2 = createConcrete("2", MutableMap.of("name", "frank")); + assertEquals(l1, l1b); + assertNotEquals(l1, l2); + } + + @Test + public void nullNameAndParentLocationIsAcceptable() { + Location location = createConcrete(MutableMap.of("name", null, "parentLocation", null)); + assertEquals(location.getDisplayName(), null); + assertEquals(location.getParent(), null); + } + + @Test + public void testSettingParentLocation() { + Location location = createConcrete(); + Location locationSub = createConcrete(); + locationSub.setParent(location); + + assertEquals(ImmutableList.copyOf(location.getChildren()), ImmutableList.of(locationSub)); + assertEquals(locationSub.getParent(), location); + } + + @Test + public void testClearingParentLocation() { + Location location = createConcrete(); + Location locationSub = createConcrete(); + locationSub.setParent(location); + + locationSub.setParent(null); + assertEquals(ImmutableList.copyOf(location.getChildren()), Collections.emptyList()); + assertEquals(locationSub.getParent(), null); + } + + @Test + public void testContainsLocation() { + Location location = createConcrete(); + Location locationSub = createConcrete(); + locationSub.setParent(location); + + assertTrue(location.containsLocation(location)); + assertTrue(location.containsLocation(locationSub)); + assertFalse(locationSub.containsLocation(location)); + } + + + @Test + public void queryingNameReturnsNameGivenInConstructor() { + String name = "Outer Mongolia"; + Location location = createConcrete(MutableMap.of("name", "Outer Mongolia")); + assertEquals(location.getDisplayName(), name);; + } + + @Test + public void constructorParentLocationReturnsExpectedLocation() { + Location parent = createConcrete(MutableMap.of("name", "Middle Earth")); + Location child = createConcrete(MutableMap.of("name", "The Shire", "parentLocation", parent)); + assertEquals(child.getParent(), parent); + assertEquals(ImmutableList.copyOf(parent.getChildren()), ImmutableList.of(child)); + } + + @Test + public void setParentLocationReturnsExpectedLocation() { + Location parent = createConcrete(MutableMap.of("name", "Middle Earth")); + Location child = createConcrete(MutableMap.of("name", "The Shire")); + child.setParent(parent); + assertEquals(child.getParent(), parent); + assertEquals(ImmutableList.copyOf(parent.getChildren()), ImmutableList.of(child)); + } + + @Test + public void testAddChildToParentLocationReturnsExpectedLocation() { + ConcreteLocation parent = createConcrete(); + Location child = createConcrete(); + parent.addChild(child); + assertEquals(child.getParent(), parent); + assertEquals(ImmutableList.copyOf(parent.getChildren()), ImmutableList.of(child)); + } + + @Test + public void testFieldSetFromFlag() { + ConcreteLocation loc = createConcrete(MutableMap.of("myfield", "myval")); + assertEquals(loc.myfield, "myval"); + } + + @Test + public void testFieldSetFromFlagUsesDefault() { + ConcreteLocation loc = createConcrete(); + assertEquals(loc.myfield, "mydefault"); + } + + @Test + public void testLocationTags() throws Exception { + LocationInternal loc = mgmt.getLocationManager().createLocation(LocationSpec.create(ConcreteLocation.class).tag("x")); + assertEquals(loc.tags().getTags(), MutableSet.of("x")); + } + +}
