http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/e2c57058/core/src/test/java/org/apache/brooklyn/location/basic/LocationExtensionsTest.java ---------------------------------------------------------------------- diff --git a/core/src/test/java/org/apache/brooklyn/location/basic/LocationExtensionsTest.java b/core/src/test/java/org/apache/brooklyn/location/basic/LocationExtensionsTest.java new file mode 100644 index 0000000..1b5b743 --- /dev/null +++ b/core/src/test/java/org/apache/brooklyn/location/basic/LocationExtensionsTest.java @@ -0,0 +1,186 @@ +/* + * 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 static org.testng.Assert.assertFalse; +import static org.testng.Assert.assertTrue; +import static org.testng.Assert.fail; +import brooklyn.entity.basic.Entities; +import org.apache.brooklyn.location.Location; +import org.apache.brooklyn.location.LocationSpec; + +import org.apache.brooklyn.api.management.ManagementContext; +import org.apache.brooklyn.test.entity.LocalManagementContextForTests; +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/e2c57058/core/src/test/java/org/apache/brooklyn/location/basic/LocationManagementTest.java ---------------------------------------------------------------------- diff --git a/core/src/test/java/org/apache/brooklyn/location/basic/LocationManagementTest.java b/core/src/test/java/org/apache/brooklyn/location/basic/LocationManagementTest.java new file mode 100644 index 0000000..be68557 --- /dev/null +++ b/core/src/test/java/org/apache/brooklyn/location/basic/LocationManagementTest.java @@ -0,0 +1,81 @@ +/* + * 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 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.management.LocationManager; +import org.apache.brooklyn.location.LocationSpec; +import org.testng.annotations.BeforeMethod; +import org.testng.annotations.Test; + +import brooklyn.entity.BrooklynAppUnitTestSupport; + +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/e2c57058/core/src/test/java/org/apache/brooklyn/location/basic/LocationPredicatesTest.java ---------------------------------------------------------------------- diff --git a/core/src/test/java/org/apache/brooklyn/location/basic/LocationPredicatesTest.java b/core/src/test/java/org/apache/brooklyn/location/basic/LocationPredicatesTest.java new file mode 100644 index 0000000..3324477 --- /dev/null +++ b/core/src/test/java/org/apache/brooklyn/location/basic/LocationPredicatesTest.java @@ -0,0 +1,99 @@ +/* + * 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.assertFalse; +import static org.testng.Assert.assertTrue; + +import org.apache.brooklyn.location.Location; +import org.apache.brooklyn.location.LocationSpec; +import org.apache.brooklyn.test.entity.LocalManagementContextForTests; +import org.apache.brooklyn.test.entity.TestEntity; +import org.testng.annotations.AfterMethod; +import org.testng.annotations.BeforeMethod; +import org.testng.annotations.Test; + +import brooklyn.entity.basic.Entities; +import brooklyn.management.internal.LocalManagementContext; + +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/e2c57058/core/src/test/java/org/apache/brooklyn/location/basic/LocationPropertiesFromBrooklynPropertiesTest.java ---------------------------------------------------------------------- diff --git a/core/src/test/java/org/apache/brooklyn/location/basic/LocationPropertiesFromBrooklynPropertiesTest.java b/core/src/test/java/org/apache/brooklyn/location/basic/LocationPropertiesFromBrooklynPropertiesTest.java new file mode 100644 index 0000000..8be1689 --- /dev/null +++ b/core/src/test/java/org/apache/brooklyn/location/basic/LocationPropertiesFromBrooklynPropertiesTest.java @@ -0,0 +1,121 @@ +/* + * 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 java.util.Map; + +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/e2c57058/core/src/test/java/org/apache/brooklyn/location/basic/LocationRegistryTest.java ---------------------------------------------------------------------- diff --git a/core/src/test/java/org/apache/brooklyn/location/basic/LocationRegistryTest.java b/core/src/test/java/org/apache/brooklyn/location/basic/LocationRegistryTest.java new file mode 100644 index 0000000..ed8a96d --- /dev/null +++ b/core/src/test/java/org/apache/brooklyn/location/basic/LocationRegistryTest.java @@ -0,0 +1,159 @@ +/* + * 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 org.apache.brooklyn.location.Location; +import org.apache.brooklyn.test.entity.LocalManagementContextForTests; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.testng.Assert; +import org.testng.annotations.AfterMethod; +import org.testng.annotations.Test; + +import brooklyn.config.BrooklynProperties; +import brooklyn.entity.basic.Entities; +import org.apache.brooklyn.location.LocationDefinition; +import brooklyn.management.internal.LocalManagementContext; + +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/e2c57058/core/src/test/java/org/apache/brooklyn/location/basic/MachineDetailsTest.java ---------------------------------------------------------------------- diff --git a/core/src/test/java/org/apache/brooklyn/location/basic/MachineDetailsTest.java b/core/src/test/java/org/apache/brooklyn/location/basic/MachineDetailsTest.java new file mode 100644 index 0000000..7b36172 --- /dev/null +++ b/core/src/test/java/org/apache/brooklyn/location/basic/MachineDetailsTest.java @@ -0,0 +1,81 @@ +/* + * 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.assertFalse; +import static org.testng.Assert.assertNotNull; + +import java.util.Arrays; + +import org.apache.brooklyn.api.management.ManagementContext; +import org.apache.brooklyn.api.management.Task; +import org.apache.brooklyn.location.LocationSpec; +import org.apache.brooklyn.location.MachineDetails; +import org.apache.brooklyn.location.OsDetails; +import org.apache.brooklyn.test.entity.TestApplication; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.testng.annotations.AfterMethod; +import org.testng.annotations.BeforeMethod; +import org.testng.annotations.Test; + +import brooklyn.entity.basic.Entities; + +public class MachineDetailsTest { + + private static final Logger LOG = LoggerFactory.getLogger(SshMachineLocationTest.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/e2c57058/core/src/test/java/org/apache/brooklyn/location/basic/MultiLocationRebindTest.java ---------------------------------------------------------------------- diff --git a/core/src/test/java/org/apache/brooklyn/location/basic/MultiLocationRebindTest.java b/core/src/test/java/org/apache/brooklyn/location/basic/MultiLocationRebindTest.java new file mode 100644 index 0000000..25c2e9e --- /dev/null +++ b/core/src/test/java/org/apache/brooklyn/location/basic/MultiLocationRebindTest.java @@ -0,0 +1,120 @@ +/* + * 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 java.io.File; +import java.util.List; + +import org.apache.brooklyn.api.entity.proxying.EntitySpec; +import org.apache.brooklyn.api.management.ManagementContext; +import org.apache.brooklyn.location.Location; +import org.apache.brooklyn.location.LocationSpec; +import org.apache.brooklyn.location.cloud.AvailabilityZoneExtension; +import org.apache.brooklyn.test.entity.TestApplication; +import org.testng.annotations.AfterMethod; +import org.testng.annotations.BeforeMethod; +import org.testng.annotations.Test; + +import brooklyn.entity.basic.ApplicationBuilder; +import brooklyn.entity.basic.Entities; +import brooklyn.entity.rebind.RebindTestUtils; +import brooklyn.test.Asserts; +import brooklyn.util.collections.MutableSet; +import brooklyn.util.net.Networking; +import brooklyn.util.os.Os; + +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/e2c57058/core/src/test/java/org/apache/brooklyn/location/basic/MultiLocationResolverTest.java ---------------------------------------------------------------------- diff --git a/core/src/test/java/org/apache/brooklyn/location/basic/MultiLocationResolverTest.java b/core/src/test/java/org/apache/brooklyn/location/basic/MultiLocationResolverTest.java new file mode 100644 index 0000000..6fbf54e --- /dev/null +++ b/core/src/test/java/org/apache/brooklyn/location/basic/MultiLocationResolverTest.java @@ -0,0 +1,199 @@ +/* + * 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 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.location.Location; +import org.apache.brooklyn.location.MachineLocation; +import org.apache.brooklyn.location.NoMachinesAvailableException; +import org.apache.brooklyn.location.cloud.AvailabilityZoneExtension; +import org.apache.brooklyn.test.entity.LocalManagementContextForTests; +import org.testng.Assert; +import org.testng.annotations.AfterMethod; +import org.testng.annotations.BeforeMethod; +import org.testng.annotations.Test; + +import brooklyn.config.BrooklynProperties; +import brooklyn.entity.basic.Entities; +import org.apache.brooklyn.location.MachineProvisioningLocation; +import brooklyn.management.internal.LocalManagementContext; +import brooklyn.util.collections.MutableList; +import brooklyn.util.collections.MutableMap; +import brooklyn.util.exceptions.Exceptions; + +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); + } + }; + } +} http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/e2c57058/core/src/test/java/org/apache/brooklyn/location/basic/MultiLocationTest.java ---------------------------------------------------------------------- diff --git a/core/src/test/java/org/apache/brooklyn/location/basic/MultiLocationTest.java b/core/src/test/java/org/apache/brooklyn/location/basic/MultiLocationTest.java new file mode 100644 index 0000000..57d6c79 --- /dev/null +++ b/core/src/test/java/org/apache/brooklyn/location/basic/MultiLocationTest.java @@ -0,0 +1,119 @@ +/* + * 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.assertTrue; + +import org.apache.brooklyn.test.entity.LocalManagementContextForTests; +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 brooklyn.entity.basic.Entities; +import org.apache.brooklyn.location.LocationSpec; +import org.apache.brooklyn.location.NoMachinesAvailableException; +import org.apache.brooklyn.location.cloud.AvailabilityZoneExtension; +import brooklyn.management.internal.LocalManagementContext; +import brooklyn.test.Asserts; +import brooklyn.util.collections.MutableSet; +import brooklyn.util.net.Networking; + +import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableMap; + +public class MultiLocationTest { + + private static final Logger log = LoggerFactory.getLogger(MultiLocationTest.class); + + private LocalManagementContext managementContext; + private SshMachineLocation mac1a; + private SshMachineLocation mac1b; + private SshMachineLocation mac2a; + private SshMachineLocation mac2b; + private FixedListMachineProvisioningLocation<SshMachineLocation> loc1; + private FixedListMachineProvisioningLocation<SshMachineLocation> loc2; + private MultiLocation<SshMachineLocation> multiLoc; + + @SuppressWarnings("unchecked") + @BeforeMethod(alwaysRun=true) + public void setUp() throws Exception { + managementContext = LocalManagementContextForTests.newInstance(); + mac1a = managementContext.getLocationManager().createLocation(LocationSpec.create(SshMachineLocation.class) + .displayName("mac1a") + .configure("address", Networking.getInetAddressWithFixedName("1.1.1.1"))); + mac1b = managementContext.getLocationManager().createLocation(LocationSpec.create(SshMachineLocation.class) + .displayName("mac1b") + .configure("address", Networking.getInetAddressWithFixedName("1.1.1.2"))); + mac2a = managementContext.getLocationManager().createLocation(LocationSpec.create(SshMachineLocation.class) + .displayName("mac2a") + .configure("address", Networking.getInetAddressWithFixedName("1.1.1.3"))); + mac2b = managementContext.getLocationManager().createLocation(LocationSpec.create(SshMachineLocation.class) + .displayName("mac2b") + .configure("address", Networking.getInetAddressWithFixedName("1.1.1.4"))); + loc1 = managementContext.getLocationManager().createLocation(LocationSpec.create(FixedListMachineProvisioningLocation.class) + .displayName("loc1") + .configure("machines", MutableSet.of(mac1a, mac1b))); + loc2 = managementContext.getLocationManager().createLocation(LocationSpec.create(FixedListMachineProvisioningLocation.class) + .displayName("loc2") + .configure("machines", MutableSet.of(mac2a, mac2b))); + multiLoc = managementContext.getLocationManager().createLocation(LocationSpec.create(MultiLocation.class) + .displayName("multiLoc") + .configure("subLocations", ImmutableList.of(loc1, loc2))); + } + + @AfterMethod(alwaysRun=true) + public void tearDown() throws Exception { + if (managementContext != null) Entities.destroyAll(managementContext); + } + + @Test + public void testHasAvailabilityZonesAsSubLocations() throws Exception { + multiLoc.hasExtension(AvailabilityZoneExtension.class); + AvailabilityZoneExtension extension = multiLoc.getExtension(AvailabilityZoneExtension.class); + Asserts.assertEqualsIgnoringOrder(extension.getAllSubLocations(), ImmutableList.of(loc1, loc2)); + Asserts.assertEqualsIgnoringOrder(extension.getSubLocations(2), ImmutableList.of(loc1, loc2)); + assertTrue(ImmutableList.of(loc1, loc2).containsAll(extension.getSubLocations(1))); + } + + @Test + public void testObtainAndReleaseDelegateToSubLocation() throws Exception { + SshMachineLocation obtained = multiLoc.obtain(ImmutableMap.of()); + assertTrue(ImmutableList.of(mac1a, mac1b, mac2a, mac2b).contains(obtained)); + multiLoc.release(obtained); + } + + @Test + public void testObtainsMovesThroughSubLocations() throws Exception { + Assert.assertEquals(multiLoc.obtain().getAddress().getHostAddress(), "1.1.1.1"); + Assert.assertEquals(multiLoc.obtain().getAddress().getHostAddress(), "1.1.1.2"); + Assert.assertEquals(multiLoc.obtain().getAddress().getHostAddress(), "1.1.1.3"); + Assert.assertEquals(multiLoc.obtain().getAddress().getHostAddress(), "1.1.1.4"); + try { + multiLoc.obtain(); + Assert.fail(); + } catch (NoMachinesAvailableException e) { + log.info("Error when no machines available across locations is: "+e); + Assert.assertTrue(e.toString().contains("loc1"), "Message should have referred to sub-location message: "+e); + } + } + +} http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/e2c57058/core/src/test/java/org/apache/brooklyn/location/basic/PaasLocationTest.java ---------------------------------------------------------------------- diff --git a/core/src/test/java/org/apache/brooklyn/location/basic/PaasLocationTest.java b/core/src/test/java/org/apache/brooklyn/location/basic/PaasLocationTest.java new file mode 100644 index 0000000..1b841d3 --- /dev/null +++ b/core/src/test/java/org/apache/brooklyn/location/basic/PaasLocationTest.java @@ -0,0 +1,35 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.brooklyn.location.basic; + +import org.apache.brooklyn.location.paas.PaasLocation; +import brooklyn.test.location.TestPaasLocation; +import org.testng.Assert; +import org.testng.annotations.Test; + +public class PaasLocationTest { + + private PaasLocation location; + + @Test + public void testProviderName(){ + location = new TestPaasLocation(); + Assert.assertEquals(location.getPaasProviderName(), "TestPaas"); + } +} http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/e2c57058/core/src/test/java/org/apache/brooklyn/location/basic/PortRangesTest.java ---------------------------------------------------------------------- diff --git a/core/src/test/java/org/apache/brooklyn/location/basic/PortRangesTest.java b/core/src/test/java/org/apache/brooklyn/location/basic/PortRangesTest.java new file mode 100644 index 0000000..3e4812f --- /dev/null +++ b/core/src/test/java/org/apache/brooklyn/location/basic/PortRangesTest.java @@ -0,0 +1,130 @@ +/* + * 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 java.util.Iterator; + +import org.testng.Assert; +import org.testng.annotations.Test; + +import org.apache.brooklyn.location.PortRange; +import brooklyn.util.flags.TypeCoercions; + +import com.google.common.collect.ImmutableList; +import com.google.common.collect.Lists; + +public class PortRangesTest { + + @Test + public void testSingleRange() { + PortRange r = PortRanges.fromInteger(1234); + assertContents(r, 1234); + } + + @Test + public void testFromCollection() { + PortRange r = PortRanges.fromCollection(ImmutableList.of(1234, 2345)); + assertContents(r, 1234, 2345); + } + + @Test + public void testFromString() { + PortRange r = PortRanges.fromString("80,8080,8000,8080-8099"); + assertContents(r, 80, 8080, 8000, + 8080, 8081, 8082, 8083, 8084, 8085, 8086, 8087, 8088, 8089, + 8090, 8091, 8092, 8093, 8094, 8095, 8096, 8097, 8098, 8099); + } + + @Test + public void testFromStringWithSpaces() { + PortRange r = PortRanges.fromString(" 80 , 8080 , 8000 , 8080 - 8099 "); + assertContents(r, 80, 8080, 8000, + 8080, 8081, 8082, 8083, 8084, 8085, 8086, 8087, 8088, 8089, + 8090, 8091, 8092, 8093, 8094, 8095, 8096, 8097, 8098, 8099); + } + + @Test + public void testFromStringWithSpacesToString() { + PortRange r = PortRanges.fromString(" 80 , 8080 , 8000 , 8080 - 8099 "); + Assert.assertEquals(r.toString(), "80,8080,8000,8080-8099"); + } + + @Test + public void testFromStringThrowsIllegalArgumentException() { + assertFromStringThrowsIllegalArgumentException("80-100000"); + assertFromStringThrowsIllegalArgumentException("0-80"); + } + + @Test + public void testCoercion() { + PortRanges.init(); + PortRange r = TypeCoercions.coerce("80", PortRange.class); + assertContents(r, 80); + } + + @Test + public void testCoercionInt() { + PortRanges.init(); + PortRange r = TypeCoercions.coerce(80, PortRange.class); + assertContents(r, 80); + } + + @Test + public void testLinearRangeOfSizeOne() throws Exception { + PortRanges.LinearPortRange range = new PortRanges.LinearPortRange(80, 80); + assertEquals(Lists.newArrayList(range), ImmutableList.of(80)); + } + + @Test + public void testLinearRangeCountingUpwards() throws Exception { + PortRanges.LinearPortRange range = new PortRanges.LinearPortRange(80, 81); + assertEquals(Lists.newArrayList(range), ImmutableList.of(80, 81)); + } + + @Test + public void testLinearRangeCountingDownwards() throws Exception { + PortRanges.LinearPortRange range = new PortRanges.LinearPortRange(80, 79); + assertEquals(Lists.newArrayList(range), ImmutableList.of(80, 79)); + } + + protected void assertFromStringThrowsIllegalArgumentException(String range) { + try { + PortRanges.fromString(range); + Assert.fail(); + } catch (IllegalArgumentException e) { + // success + } + } + + private static <T> void assertContents(Iterable<T> actual, T ...expected) { + Iterator<T> i = actual.iterator(); + int c = 0; + while (i.hasNext()) { + if (expected.length<=c) { + Assert.fail("Iterable contained more than the "+c+" expected elements"); + } + Assert.assertEquals(i.next(), expected[c++]); + } + if (expected.length>c) { + Assert.fail("Iterable contained only "+c+" elements, "+expected.length+" expected"); + } + } +} http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/e2c57058/core/src/test/java/org/apache/brooklyn/location/basic/RecordingMachineLocationCustomizer.java ---------------------------------------------------------------------- diff --git a/core/src/test/java/org/apache/brooklyn/location/basic/RecordingMachineLocationCustomizer.java b/core/src/test/java/org/apache/brooklyn/location/basic/RecordingMachineLocationCustomizer.java new file mode 100644 index 0000000..a30d6e1 --- /dev/null +++ b/core/src/test/java/org/apache/brooklyn/location/basic/RecordingMachineLocationCustomizer.java @@ -0,0 +1,71 @@ +/* + * 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 com.google.common.base.Preconditions.checkNotNull; + +import java.util.List; + +import com.google.common.base.Objects; +import com.google.common.collect.ImmutableList; +import com.google.common.collect.Lists; + +import org.apache.brooklyn.location.MachineLocation; +import org.apache.brooklyn.location.MachineLocationCustomizer; + +public class RecordingMachineLocationCustomizer implements MachineLocationCustomizer { + public static class Call { + public final String methodName; + public final List<?> args; + + Call(String methodName, List<?> args) { + this.methodName = checkNotNull(methodName); + this.args = checkNotNull(args); + } + + @Override + public String toString() { + return methodName+args; + } + + @Override + public int hashCode() { + return Objects.hashCode(methodName, args); + } + + @Override + public boolean equals(Object other) { + return (other instanceof RecordingMachineLocationCustomizer.Call) && + methodName.equals(((RecordingMachineLocationCustomizer.Call)other).methodName) && + args.equals(((RecordingMachineLocationCustomizer.Call)other).args); + } + } + + public final List<RecordingMachineLocationCustomizer.Call> calls = Lists.newCopyOnWriteArrayList(); + + @Override + public void customize(MachineLocation machine) { + calls.add(new Call("customize", ImmutableList.of(machine))); + } + + @Override + public void preRelease(MachineLocation machine) { + calls.add(new Call("preRelease", ImmutableList.of(machine))); + } +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/e2c57058/core/src/test/java/org/apache/brooklyn/location/basic/SimulatedLocation.java ---------------------------------------------------------------------- diff --git a/core/src/test/java/org/apache/brooklyn/location/basic/SimulatedLocation.java b/core/src/test/java/org/apache/brooklyn/location/basic/SimulatedLocation.java new file mode 100644 index 0000000..c904619 --- /dev/null +++ b/core/src/test/java/org/apache/brooklyn/location/basic/SimulatedLocation.java @@ -0,0 +1,136 @@ +/* + * 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 java.net.InetAddress; +import java.util.Collection; +import java.util.Map; +import java.util.Set; + +import org.apache.brooklyn.location.HardwareDetails; +import org.apache.brooklyn.location.LocationSpec; +import org.apache.brooklyn.location.MachineDetails; +import org.apache.brooklyn.location.MachineLocation; +import org.apache.brooklyn.location.MachineProvisioningLocation; +import org.apache.brooklyn.location.OsDetails; +import org.apache.brooklyn.location.PortRange; +import org.apache.brooklyn.location.PortSupplier; +import brooklyn.util.collections.MutableMap; +import brooklyn.util.net.Networking; + +import com.google.common.collect.ImmutableSet; +import com.google.common.collect.Iterables; +import com.google.common.collect.Sets; + + +/** Location for use in dev/test, defining custom start/stop support, and/or tweaking the ports which are permitted to be available + * (using setPermittedPorts(Iterable)) + */ +public class SimulatedLocation extends AbstractLocation implements MachineProvisioningLocation<MachineLocation>, MachineLocation, PortSupplier { + + private static final long serialVersionUID = 1L; + + private static final InetAddress address; + static { + address = Networking.getLocalHost(); + } + + Iterable<Integer> permittedPorts = PortRanges.fromString("1+"); + Set<Integer> usedPorts = Sets.newLinkedHashSet(); + + public SimulatedLocation() { + this(MutableMap.<String,Object>of()); + } + public SimulatedLocation(Map<String,? extends Object> flags) { + super(flags); + } + + @Override + public SimulatedLocation newSubLocation(Map<?,?> newFlags) { + // TODO shouldn't have to copy config bag as it should be inherited (but currently it is not used inherited everywhere; just most places) + return getManagementContext().getLocationManager().createLocation(LocationSpec.create(getClass()) + .parent(this) + .configure(config().getLocalBag().getAllConfig()) // FIXME Should this just be inherited? + .configure(newFlags)); + } + + public MachineLocation obtain(Map<?,?> flags) { + return this; + } + + public void release(MachineLocation machine) { + } + + public Map<String,Object> getProvisioningFlags(Collection<String> tags) { + return MutableMap.<String,Object>of(); + } + + public InetAddress getAddress() { + return address; + } + + @Override + public String getHostname() { + String hostname = address.getHostName(); + return (hostname == null || hostname.equals(address.getHostAddress())) ? null : hostname; + } + + @Override + public Set<String> getPublicAddresses() { + return ImmutableSet.of(address.getHostAddress()); + } + + @Override + public Set<String> getPrivateAddresses() { + return ImmutableSet.of(); + } + + public synchronized boolean obtainSpecificPort(int portNumber) { + if (!Iterables.contains(permittedPorts, portNumber)) return false; + if (usedPorts.contains(portNumber)) return false; + usedPorts.add(portNumber); + return true; + } + + public synchronized int obtainPort(PortRange range) { + for (int p: range) + if (obtainSpecificPort(p)) return p; + return -1; + } + + public synchronized void releasePort(int portNumber) { + usedPorts.remove(portNumber); + } + + public synchronized void setPermittedPorts(Iterable<Integer> ports) { + permittedPorts = ports; + } + + @Override + public OsDetails getOsDetails() { + return getMachineDetails().getOsDetails(); + } + + @Override + public MachineDetails getMachineDetails() { + HardwareDetails hardwareDetails = new BasicHardwareDetails(null, null); + OsDetails osDetails = BasicOsDetails.Factory.ANONYMOUS_LINUX; + return new BasicMachineDetails(hardwareDetails, osDetails); + } +} http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/e2c57058/core/src/test/java/org/apache/brooklyn/location/basic/SingleMachineLocationResolverTest.java ---------------------------------------------------------------------- diff --git a/core/src/test/java/org/apache/brooklyn/location/basic/SingleMachineLocationResolverTest.java b/core/src/test/java/org/apache/brooklyn/location/basic/SingleMachineLocationResolverTest.java new file mode 100644 index 0000000..a9da0dd --- /dev/null +++ b/core/src/test/java/org/apache/brooklyn/location/basic/SingleMachineLocationResolverTest.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.basic; + +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.test.entity.LocalManagementContextForTests; +import org.testng.annotations.AfterMethod; +import org.testng.annotations.BeforeMethod; +import org.testng.annotations.Test; + +import brooklyn.config.BrooklynProperties; +import brooklyn.entity.basic.Entities; +import brooklyn.management.internal.LocalManagementContext; + +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/e2c57058/core/src/test/java/org/apache/brooklyn/location/basic/SingleMachineProvisioningLocationTest.java ---------------------------------------------------------------------- diff --git a/core/src/test/java/org/apache/brooklyn/location/basic/SingleMachineProvisioningLocationTest.java b/core/src/test/java/org/apache/brooklyn/location/basic/SingleMachineProvisioningLocationTest.java new file mode 100644 index 0000000..7d42e88 --- /dev/null +++ b/core/src/test/java/org/apache/brooklyn/location/basic/SingleMachineProvisioningLocationTest.java @@ -0,0 +1,64 @@ +/* + * 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.assertNotNull; + +import org.apache.brooklyn.test.entity.LocalManagementContextForTests; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.testng.annotations.AfterMethod; +import org.testng.annotations.BeforeMethod; +import org.testng.annotations.Test; + +import brooklyn.management.internal.LocalManagementContext; + +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/e2c57058/core/src/test/java/org/apache/brooklyn/location/basic/SshMachineLocationIntegrationTest.java ---------------------------------------------------------------------- diff --git a/core/src/test/java/org/apache/brooklyn/location/basic/SshMachineLocationIntegrationTest.java b/core/src/test/java/org/apache/brooklyn/location/basic/SshMachineLocationIntegrationTest.java new file mode 100644 index 0000000..68a53c5 --- /dev/null +++ b/core/src/test/java/org/apache/brooklyn/location/basic/SshMachineLocationIntegrationTest.java @@ -0,0 +1,141 @@ +/* + * 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 java.io.ByteArrayOutputStream; +import java.security.KeyPair; +import java.util.Arrays; +import java.util.Map; + +import brooklyn.util.internal.ssh.SshTool; + +import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableMap; + +import org.apache.brooklyn.api.management.ManagementContext; +import org.apache.brooklyn.test.entity.LocalManagementContextForTests; +import org.apache.brooklyn.test.entity.TestApplication; +import org.testng.Assert; +import org.testng.annotations.AfterMethod; +import org.testng.annotations.BeforeMethod; +import org.testng.annotations.Test; + +import brooklyn.entity.basic.Entities; +import brooklyn.util.collections.MutableMap; +import brooklyn.util.crypto.SecureKeys; +import brooklyn.util.internal.ssh.sshj.SshjTool; +import brooklyn.util.internal.ssh.sshj.SshjTool.SshjToolBuilder; + +import com.google.common.base.Preconditions; + +import static org.testng.Assert.assertEquals; + +public class SshMachineLocationIntegrationTest { + + protected TestApplication app; + protected ManagementContext mgmt; + + @BeforeMethod(alwaysRun=true) + public void setup() throws Exception { + mgmt = LocalManagementContextForTests.builder(true) + .useDefaultProperties() + .build(); + app = TestApplication.Factory.newManagedInstanceForTests(mgmt); + } + + @AfterMethod(alwaysRun=true) + public void tearDown() throws Exception { + if (mgmt != null) Entities.destroyAll(mgmt); + mgmt = null; + } + + // Note: requires `named:localhost-passphrase` set up with a key whose passphrase is "localhost" + // * create the key with: + // ssh-keygen -t rsa -N "brooklyn" -f ~/.ssh/id_rsa_passphrase + // ssh-copy-id localhost + // * create brooklyn.properties, containing: + // brooklyn.location.named.localhost-passphrase=localhost + // brooklyn.location.named.localhost-passphrase.privateKeyFile=~/.ssh/id_rsa_passphrase + // brooklyn.location.named.localhost-passphrase.privateKeyPassphrase=brooklyn + @Test(groups = "Integration") + public void testExtractingConnectablePassphraselessKey() throws Exception { + LocalhostMachineProvisioningLocation lhp = (LocalhostMachineProvisioningLocation) mgmt.getLocationRegistry().resolve("named:localhost-passphrase", true, null).orNull(); + Preconditions.checkNotNull(lhp, "This test requires a localhost named location called 'localhost-passphrase' (which should have a passphrase set)"); + SshMachineLocation sm = lhp.obtain(); + + SshjToolBuilder builder = SshjTool.builder().host(sm.getAddress().getHostName()).user(sm.getUser()); + + KeyPair data = sm.findKeyPair(); + if (data!=null) builder.privateKeyData(SecureKeys.toPem(data)); + String password = sm.findPassword(); + if (password!=null) builder.password(password); + SshjTool tool = builder.build(); + tool.connect(); + ByteArrayOutputStream out = new ByteArrayOutputStream(); + int result = tool.execCommands(MutableMap.<String,Object>of("out", out), Arrays.asList("date")); + Assert.assertTrue(out.toString().contains(" 20"), "out="+out); + assertEquals(result, 0); + } + + @Test(groups = "Integration") + public void testExecScriptScriptDirFlagIsRespected() throws Exception { + // For explanation of (some of) the magic behind this command, see http://stackoverflow.com/a/229606/68898 + final String command = "if [[ \"$0\" == \"/var/tmp/\"* ]]; then true; else false; fi"; + + LocalhostMachineProvisioningLocation lhp = (LocalhostMachineProvisioningLocation) mgmt.getLocationRegistry().resolve("localhost", true, null).orNull(); + SshMachineLocation sm = lhp.obtain(); + + Map<String, Object> props = ImmutableMap.<String, Object>builder() + .put(SshTool.PROP_SCRIPT_DIR.getName(), "/var/tmp") + .build(); + int rc = sm.execScript(props, "Test script directory execution", ImmutableList.of(command)); + assertEquals(rc, 0); + } + + @Test(groups = "Integration") + public void testLocationScriptDirConfigIsRespected() throws Exception { + // For explanation of (some of) the magic behind this command, see http://stackoverflow.com/a/229606/68898 + final String command = "if [[ \"$0\" == \"/var/tmp/\"* ]]; then true; else false; fi"; + + Map<String, Object> locationConfig = ImmutableMap.<String, Object>builder() + .put(SshMachineLocation.SCRIPT_DIR.getName(), "/var/tmp") + .build(); + + LocalhostMachineProvisioningLocation lhp = (LocalhostMachineProvisioningLocation) mgmt.getLocationRegistry().resolve("localhost", locationConfig); + SshMachineLocation sm = lhp.obtain(); + + int rc = sm.execScript("Test script directory execution", ImmutableList.of(command)); + assertEquals(rc, 0); + } + + @Test(groups = "Integration") + public void testMissingLocationScriptDirIsAlsoOkay() throws Exception { + final String command = "echo hello"; + + Map<String, Object> locationConfig = ImmutableMap.<String, Object>builder() +// .put(SshMachineLocation.SCRIPT_DIR.getName(), "/var/tmp") + .build(); + + LocalhostMachineProvisioningLocation lhp = (LocalhostMachineProvisioningLocation) mgmt.getLocationRegistry().resolve("localhost", locationConfig); + SshMachineLocation sm = lhp.obtain(); + + int rc = sm.execScript("Test script directory execution", ImmutableList.of(command)); + assertEquals(rc, 0); + } +}
