http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/e2c57058/core/src/test/java/org/apache/brooklyn/location/basic/FixedListMachineProvisioningLocationTest.java ---------------------------------------------------------------------- diff --git a/core/src/test/java/org/apache/brooklyn/location/basic/FixedListMachineProvisioningLocationTest.java b/core/src/test/java/org/apache/brooklyn/location/basic/FixedListMachineProvisioningLocationTest.java new file mode 100644 index 0000000..d689512 --- /dev/null +++ b/core/src/test/java/org/apache/brooklyn/location/basic/FixedListMachineProvisioningLocationTest.java @@ -0,0 +1,575 @@ +/* + * 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.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.location.LocationSpec; +import org.apache.brooklyn.location.MachineLocation; +import org.apache.brooklyn.location.NoMachinesAvailableException; +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 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; + +import brooklyn.config.ConfigKey; +import brooklyn.entity.basic.ConfigKeys; +import brooklyn.entity.basic.Entities; +import brooklyn.management.internal.LocalManagementContext; +import brooklyn.util.collections.MutableList; +import brooklyn.util.collections.MutableMap; +import brooklyn.util.net.Networking; +import brooklyn.util.stream.Streams; + +/** + * 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/e2c57058/core/src/test/java/org/apache/brooklyn/location/basic/HostLocationResolverTest.java ---------------------------------------------------------------------- diff --git a/core/src/test/java/org/apache/brooklyn/location/basic/HostLocationResolverTest.java b/core/src/test/java/org/apache/brooklyn/location/basic/HostLocationResolverTest.java new file mode 100644 index 0000000..2d66cb5 --- /dev/null +++ b/core/src/test/java/org/apache/brooklyn/location/basic/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.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.location.MachineProvisioningLocation; +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 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/e2c57058/core/src/test/java/org/apache/brooklyn/location/basic/LegacyAbstractLocationTest.java ---------------------------------------------------------------------- diff --git a/core/src/test/java/org/apache/brooklyn/location/basic/LegacyAbstractLocationTest.java b/core/src/test/java/org/apache/brooklyn/location/basic/LegacyAbstractLocationTest.java new file mode 100644 index 0000000..10e59b3 --- /dev/null +++ b/core/src/test/java/org/apache/brooklyn/location/basic/LegacyAbstractLocationTest.java @@ -0,0 +1,151 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.brooklyn.location.basic; + +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.testng.annotations.AfterMethod; +import org.testng.annotations.Test; + +import brooklyn.util.collections.MutableMap; +import brooklyn.util.flags.SetFromFlag; + +import com.google.common.collect.ImmutableList; + +public class LegacyAbstractLocationTest { + + private static class ConcreteLocation extends AbstractLocation { + @SetFromFlag(defaultVal="mydefault") + String myfield; + + public ConcreteLocation() { + super(); + } + + public ConcreteLocation(Map properties) { + super(properties); + } + } + + @AfterMethod(alwaysRun = true) + public void tearDown(){ + // nothing to tear down; did not create a management context + } + + @Test + public void testEquals() { + AbstractLocation l1 = new ConcreteLocation(MutableMap.of("id", "1", "name", "bob")); + AbstractLocation l2 = new ConcreteLocation(MutableMap.of("id", "1", "name", "frank")); + AbstractLocation l3 = new ConcreteLocation(MutableMap.of("id", "2", "name", "frank")); + assertEquals(l1, l2); + assertNotEquals(l2, l3); + } + + @Test + public void nullNameAndParentLocationIsAcceptable() { + AbstractLocation location = new ConcreteLocation(MutableMap.of("name", null, "parentLocation", null)); + assertEquals(location.getDisplayName(), null); + assertEquals(location.getParent(), null); + } + + @Test + public void testSettingParentLocation() { + AbstractLocation location = new ConcreteLocation(); + AbstractLocation locationSub = new ConcreteLocation(); + locationSub.setParent(location); + + assertEquals(ImmutableList.copyOf(location.getChildren()), ImmutableList.of(locationSub)); + assertEquals(locationSub.getParent(), location); + } + + @Test + public void testClearingParentLocation() { + AbstractLocation location = new ConcreteLocation(); + AbstractLocation locationSub = new ConcreteLocation(); + locationSub.setParent(location); + + locationSub.setParent(null); + assertEquals(ImmutableList.copyOf(location.getChildren()), Collections.emptyList()); + assertEquals(locationSub.getParent(), null); + } + + @Test + public void testContainsLocation() { + AbstractLocation location = new ConcreteLocation(); + AbstractLocation locationSub = new ConcreteLocation(); + locationSub.setParent(location); + + assertTrue(location.containsLocation(location)); + assertTrue(location.containsLocation(locationSub)); + assertFalse(locationSub.containsLocation(location)); + } + + + @Test + public void queryingNameReturnsNameGivenInConstructor() { + String name = "Outer Mongolia"; + AbstractLocation location = new ConcreteLocation(MutableMap.of("name", "Outer Mongolia")); + assertEquals(location.getDisplayName(), name);; + } + + @Test + public void constructorParentLocationReturnsExpectedLocation() { + AbstractLocation parent = new ConcreteLocation(MutableMap.of("name", "Middle Earth")); + AbstractLocation child = new ConcreteLocation(MutableMap.of("name", "The Shire", "parentLocation", parent)); + assertEquals(child.getParent(), parent); + assertEquals(ImmutableList.copyOf(parent.getChildren()), ImmutableList.of(child)); + } + + @Test + public void setParentLocationReturnsExpectedLocation() { + AbstractLocation parent = new ConcreteLocation(MutableMap.of("name", "Middle Earth")); + AbstractLocation child = new ConcreteLocation(MutableMap.of("name", "The Shire")); + child.setParent(parent); + assertEquals(child.getParent(), parent); + assertEquals(ImmutableList.copyOf(parent.getChildren()), ImmutableList.of(child)); + } + + @Test + public void testAddChildToParentLocationReturnsExpectedLocation() { + AbstractLocation parent = new ConcreteLocation(MutableMap.of("id", "1")); + AbstractLocation child = new ConcreteLocation(MutableMap.of("id", "2")); + parent.addChild(child); + assertEquals(child.getParent(), parent); + assertEquals(ImmutableList.copyOf(parent.getChildren()), ImmutableList.of(child)); + } + + @Test + public void testFieldSetFromFlag() { + ConcreteLocation loc = new ConcreteLocation(MutableMap.of("myfield", "myval")); + assertEquals(loc.myfield, "myval"); + } + + @Test + public void testFieldSetFromFlagUsesDefault() { + ConcreteLocation loc = new ConcreteLocation(); + assertEquals(loc.myfield, "mydefault"); + } + +} http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/e2c57058/core/src/test/java/org/apache/brooklyn/location/basic/LocalhostLocationResolverTest.java ---------------------------------------------------------------------- diff --git a/core/src/test/java/org/apache/brooklyn/location/basic/LocalhostLocationResolverTest.java b/core/src/test/java/org/apache/brooklyn/location/basic/LocalhostLocationResolverTest.java new file mode 100644 index 0000000..fd6f29c --- /dev/null +++ b/core/src/test/java/org/apache/brooklyn/location/basic/LocalhostLocationResolverTest.java @@ -0,0 +1,265 @@ +/* + * 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.assertTrue; +import static org.testng.Assert.fail; + +import java.util.List; +import java.util.Map; +import java.util.NoSuchElementException; + +import org.apache.brooklyn.location.Location; +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.NoMachinesAvailableException; +import brooklyn.management.internal.LocalManagementContext; +import brooklyn.util.text.StringEscapes.JavaStringEscapes; + +import com.google.common.collect.ImmutableList; + +public class LocalhostLocationResolverTest { + + 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 testTakesLocalhostScopedProperties() { + brooklynProperties.put("brooklyn.location.localhost.privateKeyFile", "myprivatekeyfile"); + brooklynProperties.put("brooklyn.location.localhost.publicKeyFile", "mypublickeyfile"); + brooklynProperties.put("brooklyn.location.localhost.privateKeyData", "myprivateKeyData"); + brooklynProperties.put("brooklyn.location.localhost.publicKeyData", "myPublicKeyData"); + brooklynProperties.put("brooklyn.location.localhost.privateKeyPassphrase", "myprivateKeyPassphrase"); + + Map<String, Object> conf = resolve("localhost").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 testTakesLocalhostDeprecatedScopedProperties() { + brooklynProperties.put("brooklyn.localhost.privateKeyFile", "myprivatekeyfile"); + brooklynProperties.put("brooklyn.localhost.publicKeyFile", "mypublickeyfile"); + brooklynProperties.put("brooklyn.localhost.privateKeyData", "myprivateKeyData"); + brooklynProperties.put("brooklyn.localhost.publicKeyData", "myPublicKeyData"); + brooklynProperties.put("brooklyn.localhost.privateKeyPassphrase", "myprivateKeyPassphrase"); + + Map<String, Object> conf = resolve("localhost").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 testTakesDeprecatedProperties() { + brooklynProperties.put("brooklyn.localhost.private-key-file", "myprivatekeyfile"); + brooklynProperties.put("brooklyn.localhost.public-key-file", "mypublickeyfile"); + brooklynProperties.put("brooklyn.localhost.private-key-data", "myprivateKeyData"); + brooklynProperties.put("brooklyn.localhost.public-key-data", "myPublicKeyData"); + brooklynProperties.put("brooklyn.localhost.private-key-passphrase", "myprivateKeyPassphrase"); + Map<String, Object> conf = resolve("localhost").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 testPropertyScopePrescedence() { + brooklynProperties.put("brooklyn.location.named.mynamed", "localhost"); + + // prefer those in "named" over everything else + brooklynProperties.put("brooklyn.location.named.mynamed.privateKeyFile", "privateKeyFile-inNamed"); + brooklynProperties.put("brooklyn.location.localhost.privateKeyFile", "privateKeyFile-inProviderSpecific"); + brooklynProperties.put("brooklyn.localhost.privateKeyFile", "privateKeyFile-inGeneric"); + + // prefer those in provider-specific over generic + brooklynProperties.put("brooklyn.location.localhost.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 testLocalhostLoads() { + Assert.assertTrue(resolve("localhost") instanceof LocalhostMachineProvisioningLocation); + } + + @Test + public void testThrowsOnInvalid() throws Exception { + assertThrowsNoSuchElement("wrongprefix"); + assertThrowsIllegalArgument("localhost(name=abc"); // no closing bracket + assertThrowsIllegalArgument("localhost(name)"); // no value for name + assertThrowsIllegalArgument("localhost(name=)"); // no value for name + } + + + @Test + public void testAcceptsList() { + List<Location> l = getLocationResolver().resolve(ImmutableList.of("localhost")); + assertEquals(l.size(), 1, "l="+l); + assertTrue(l.get(0) instanceof LocalhostMachineProvisioningLocation, "l="+l); + } + + @SuppressWarnings("unchecked") + @Test + public void testRegistryCommaResolution() throws NoMachinesAvailableException { + List<Location> l; + l = getLocationResolver().resolve(JavaStringEscapes.unwrapJsonishListIfPossible("localhost,localhost,localhost")); + assertEquals(l.size(), 3, "l="+l); + assertTrue(l.get(0) instanceof LocalhostMachineProvisioningLocation, "l="+l); + assertTrue(l.get(1) instanceof LocalhostMachineProvisioningLocation, "l="+l); + assertTrue(l.get(2) instanceof LocalhostMachineProvisioningLocation, "l="+l); + + // And check works if comma in brackets + l = getLocationResolver().resolve(JavaStringEscapes.unwrapJsonishListIfPossible( + "[ \"byon:(hosts=\\\"192.168.0.1\\\",user=bob)\", \"byon:(hosts=\\\"192.168.0.2\\\",user=bob2)\" ]")); + assertEquals(l.size(), 2, "l="+l); + assertTrue(l.get(0) instanceof FixedListMachineProvisioningLocation, "l="+l); + assertTrue(l.get(1) instanceof FixedListMachineProvisioningLocation, "l="+l); + assertEquals(((FixedListMachineProvisioningLocation<SshMachineLocation>)l.get(0)).obtain().getUser(), "bob"); + assertEquals(((FixedListMachineProvisioningLocation<SshMachineLocation>)l.get(1)).obtain().getUser(), "bob2"); + } + + @Test(expectedExceptions={NoSuchElementException.class}) + public void testRegistryCommaResolutionInListNotAllowed1() throws NoMachinesAvailableException { + // disallowed since 0.7.0 + getLocationResolver().resolve(ImmutableList.of("localhost,localhost,localhost")); + } + + @Test(expectedExceptions={IllegalArgumentException.class}) + public void testRegistryCommaResolutionInListNotAllowed2() throws NoMachinesAvailableException { + // disallowed since 0.7.0 + // fails because it interprets the entire string as a single spec, which does not parse + getLocationResolver().resolve(ImmutableList.of("localhost(),localhost()")); + } + + @Test(expectedExceptions={IllegalArgumentException.class}) + public void testRegistryCommaResolutionInListNotAllowed3() throws NoMachinesAvailableException { + // disallowed since 0.7.0 + // fails because it interprets the entire string as a single spec, which does not parse + getLocationResolver().resolve(ImmutableList.of("localhost(name=a),localhost(name=b)")); + } + + @Test(expectedExceptions={IllegalArgumentException.class}) + public void testDoesNotAcceptsListOLists() { + ((BasicLocationRegistry)managementContext.getLocationRegistry()).resolve(ImmutableList.of(ImmutableList.of("localhost"))); + } + + @Test + public void testResolvesExplicitName() throws Exception { + Location location = resolve("localhost(name=myname)"); + assertTrue(location instanceof LocalhostMachineProvisioningLocation); + assertEquals(location.getDisplayName(), "myname"); + } + + @Test + public void testWithOldStyleColon() throws Exception { + Location location = resolve("localhost:(name=myname)"); + assertTrue(location instanceof LocalhostMachineProvisioningLocation); + assertEquals(location.getDisplayName(), "myname"); + } + + @Test + public void testResolvesPropertiesInSpec() throws Exception { + LocationInternal location = resolve("localhost(privateKeyFile=myprivatekeyfile,name=myname)"); + assertTrue(location instanceof LocalhostMachineProvisioningLocation); + assertEquals(location.getDisplayName(), "myname"); + assertEquals(location.config().getBag().getStringKey("privateKeyFile"), "myprivatekeyfile"); + } + + @Test + public void testResolvesDefaultName() throws Exception { + Location location = resolve("localhost"); + assertTrue(location instanceof LocalhostMachineProvisioningLocation); + assertEquals(location.getDisplayName(), "localhost"); + + Location location2 = resolve("localhost()"); + assertTrue(location2 instanceof LocalhostMachineProvisioningLocation); + assertEquals(location2.getDisplayName(), "localhost"); + } + + private BasicLocationRegistry getLocationResolver() { + return (BasicLocationRegistry) managementContext.getLocationRegistry(); + } + + private LocationInternal resolve(String val) { + Location l = managementContext.getLocationRegistry().resolve(val); + Assert.assertNotNull(l); + return (LocationInternal) l; + } + + private void assertThrowsNoSuchElement(String val) { + try { + resolve(val); + fail(); + } catch (NoSuchElementException e) { + // success + } + + // and check the long form returns an Absent (not throwing) + Assert.assertTrue(managementContext.getLocationRegistry().resolve(val, false, null).isAbsent()); + } + + private void assertThrowsIllegalArgument(String val) { + try { + resolve(val); + fail(); + } catch (IllegalArgumentException e) { + // success + } + + // and check the long form returns an Absent (not throwing) + Assert.assertTrue(managementContext.getLocationRegistry().resolve(val, false, null).isAbsent()); + } +} http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/e2c57058/core/src/test/java/org/apache/brooklyn/location/basic/LocalhostMachineProvisioningLocationTest.java ---------------------------------------------------------------------- diff --git a/core/src/test/java/org/apache/brooklyn/location/basic/LocalhostMachineProvisioningLocationTest.java b/core/src/test/java/org/apache/brooklyn/location/basic/LocalhostMachineProvisioningLocationTest.java new file mode 100644 index 0000000..d948eaf --- /dev/null +++ b/core/src/test/java/org/apache/brooklyn/location/basic/LocalhostMachineProvisioningLocationTest.java @@ -0,0 +1,213 @@ +/* + * 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.assertNotNull; +import static org.testng.Assert.fail; + +import java.net.ServerSocket; + +import org.apache.brooklyn.test.entity.LocalManagementContextForTests; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.testng.Assert; +import org.testng.annotations.AfterClass; +import org.testng.annotations.BeforeClass; +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.MachineProvisioningLocation; +import org.apache.brooklyn.location.NoMachinesAvailableException; +import org.apache.brooklyn.location.PortRange; +import org.apache.brooklyn.location.geo.HostGeoInfo; +import brooklyn.management.internal.LocalManagementContext; +import brooklyn.util.collections.MutableMap; +import brooklyn.util.net.Networking; + +public class LocalhostMachineProvisioningLocationTest { + + private static final Logger log = LoggerFactory.getLogger(LocalhostMachineProvisioningLocationTest.class); + + private LocalManagementContext mgmt; + + @BeforeMethod + @AfterClass + protected void clearStatics() { + LocalhostMachineProvisioningLocation.clearStaticData(); + } + + @BeforeClass + protected void setup() { + mgmt = LocalManagementContextForTests.newInstance(); + } + + @AfterClass + protected void teardown() { + Entities.destroyAll(mgmt); + } + + protected LocalhostMachineProvisioningLocation newLocalhostProvisioner() { + return mgmt.getLocationManager().createLocation(LocationSpec.create(LocalhostMachineProvisioningLocation.class)); + } + + protected LocalhostMachineProvisioningLocation newLocalhostProvisionerWithAddress(String address) { + return mgmt.getLocationManager().createLocation(LocationSpec.create(LocalhostMachineProvisioningLocation.class) + .configure("address", address)); + } + + @Test + public void defaultInvocationCanProvisionALocalhostInstance() throws Exception { + LocalhostMachineProvisioningLocation provisioner = mgmt.getLocationManager().createLocation(LocationSpec.create(LocalhostMachineProvisioningLocation.class)); + SshMachineLocation machine = provisioner.obtain(); + assertNotNull(machine); + assertEquals(machine.address, Networking.getLocalHost()); + } + + @Test + public void testUsesLocationNameProvided() throws Exception { + LocalhostMachineProvisioningLocation provisioner = newLocalhostProvisionerWithAddress("localhost"); + assertEquals(((SshMachineLocation)provisioner.obtain()).getAddress().getHostName(), "localhost"); + + LocalhostMachineProvisioningLocation provisioner2 = newLocalhostProvisionerWithAddress("1.2.3.4"); + assertEquals(((SshMachineLocation)provisioner2.obtain()).getAddress().getHostName(), "1.2.3.4"); + + LocalhostMachineProvisioningLocation provisioner3 = newLocalhostProvisionerWithAddress("127.0.0.1"); + assertEquals(((SshMachineLocation)provisioner3.obtain()).getAddress().getHostName(), "127.0.0.1"); + } + + public void provisionWithASpecificNumberOfInstances() throws NoMachinesAvailableException { + LocalhostMachineProvisioningLocation provisioner = mgmt.getLocationManager().createLocation(LocationSpec.create(LocalhostMachineProvisioningLocation.class) + .configure("count", 2)); + + // first machine + SshMachineLocation first = provisioner.obtain(); + assertNotNull(first); + assertEquals(first.address, Networking.getLocalHost()); + + // second machine + SshMachineLocation second = provisioner.obtain(); + assertNotNull(second); + assertEquals(second.address, Networking.getLocalHost()); + + // third machine - fails + try { + SshMachineLocation third = provisioner.obtain(); + fail("did not throw expected exception; got "+third); + } catch (NoMachinesAvailableException e) { + /* expected */ + } + } + + @Test + public void obtainTwoAddressesInRangeThenDontObtain() throws Exception { + LocalhostMachineProvisioningLocation p = newLocalhostProvisioner(); + SshMachineLocation m = p.obtain(); + + // Find two ports that are free, rather than risk false-negatives if a port was left open by something else. + int start = 48311; + while (true) { + if (Networking.isPortAvailable(m.getAddress(), start) && Networking.isPortAvailable(m.getAddress(), start+1)) { + break; + } else { + start++; + } + } + PortRange r = PortRanges.fromString(""+start+"-"+(start+1)); + + try { + int i1 = m.obtainPort(r); + Assert.assertEquals(i1, start); + int i2 = m.obtainPort(r); + Assert.assertEquals(i2, start+1); + + //should fail + int i3 = m.obtainPort(r); + Assert.assertEquals(i3, -1); + + //releasing and reapplying should succed + m.releasePort(i2); + int i4 = m.obtainPort(r); + Assert.assertEquals(i4, i2); + + } finally { + m.releasePort(start); + m.releasePort(start+1); + } + } + + @Test + public void obtainLowNumberedPortsAutomatically() throws Exception { + LocalhostMachineProvisioningLocation p = newLocalhostProvisioner(); + SshMachineLocation m = p.obtain(); + int start = 983; //random rarely used port, not that it matters + try { + int actual = m.obtainPort(PortRanges.fromInteger(start)); + Assert.assertEquals(actual, start); + } finally { + m.releasePort(start); + } + + } + + @Test + public void obtainPortFailsIfInUse() throws Exception { + LocalhostMachineProvisioningLocation p = newLocalhostProvisioner(); + SshMachineLocation m = p.obtain(); + + // Find two ports that are free, rather than risk false-negatives if a port was left open by something else. + int start = 48311; + while (true) { + if (Networking.isPortAvailable(m.getAddress(), start) && Networking.isPortAvailable(m.getAddress(), start+1)) { + break; + } else { + start++; + } + } + PortRange r = PortRanges.fromString(""+start+"-"+(start+1)); + + ServerSocket ss = null; + try { + ss = new ServerSocket(start, 0, m.getAddress()); + int i1 = m.obtainPort(r); + Assert.assertEquals(i1, start+1); + } finally { + if (ss!=null) ss.close(); + m.releasePort(start); + m.releasePort(start+1); + } + } + + @Test + public void obtainLocationWithGeography() throws Exception { + mgmt.getBrooklynProperties().put("brooklyn.location.named.lhx", "localhost"); + // bogus location so very little chance of it being what maxmind returns! + mgmt.getBrooklynProperties().put("brooklyn.location.named.lhx.latitude", 42d); + mgmt.getBrooklynProperties().put("brooklyn.location.named.lhx.longitude", -20d); + MachineProvisioningLocation<?> p = (MachineProvisioningLocation<?>) mgmt.getLocationRegistry().resolve("named:lhx"); + SshMachineLocation m = (SshMachineLocation) p.obtain(MutableMap.of()); + HostGeoInfo geo = HostGeoInfo.fromLocation(m); + log.info("Geo info for "+m+" is: "+geo); + Assert.assertEquals(geo.latitude, 42d, 0.00001); + Assert.assertEquals(geo.longitude, -20d, 0.00001); + } + +} http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/e2c57058/core/src/test/java/org/apache/brooklyn/location/basic/LocalhostProvisioningAndAccessTest.java ---------------------------------------------------------------------- diff --git a/core/src/test/java/org/apache/brooklyn/location/basic/LocalhostProvisioningAndAccessTest.java b/core/src/test/java/org/apache/brooklyn/location/basic/LocalhostProvisioningAndAccessTest.java new file mode 100644 index 0000000..fad4567 --- /dev/null +++ b/core/src/test/java/org/apache/brooklyn/location/basic/LocalhostProvisioningAndAccessTest.java @@ -0,0 +1,58 @@ +/* + * 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.assertTrue; + +import java.util.Arrays; + +import org.apache.brooklyn.location.Location; +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; + +public class LocalhostProvisioningAndAccessTest { + + private LocalManagementContext mgmt; + + @BeforeMethod(alwaysRun=true) + public void setUp() throws Exception { + mgmt = new LocalManagementContext(BrooklynProperties.Factory.newDefault()); + } + + @AfterMethod(alwaysRun = true) + public void tearDown(){ + if (mgmt != null) Entities.destroyAll(mgmt); + } + + @Test(groups="Integration") + public void testProvisionAndConnect() throws Exception { + Location location = mgmt.getLocationRegistry().resolve("localhost"); + assertTrue(location instanceof LocalhostMachineProvisioningLocation); + SshMachineLocation m = ((LocalhostMachineProvisioningLocation)location).obtain(); + int result = m.execCommands("test", Arrays.asList("echo hello world")); + assertEquals(result, 0); + } + +} http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/e2c57058/core/src/test/java/org/apache/brooklyn/location/basic/LocationConfigTest.java ---------------------------------------------------------------------- diff --git a/core/src/test/java/org/apache/brooklyn/location/basic/LocationConfigTest.java b/core/src/test/java/org/apache/brooklyn/location/basic/LocationConfigTest.java new file mode 100644 index 0000000..b3e4f04 --- /dev/null +++ b/core/src/test/java/org/apache/brooklyn/location/basic/LocationConfigTest.java @@ -0,0 +1,203 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.brooklyn.location.basic; + +import static org.testng.Assert.assertEquals; + +import org.apache.brooklyn.api.management.ManagementContext; +import org.apache.brooklyn.location.LocationSpec; +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.ConfigKey; +import brooklyn.entity.basic.ConfigKeys; +import brooklyn.entity.basic.Entities; +import brooklyn.util.flags.SetFromFlag; + +import com.google.common.collect.ImmutableMap; + +public class LocationConfigTest { + + // TODO Duplication of LocationConfigTest, but with locations instead of entities + + private ManagementContext managementContext; + + @BeforeMethod(alwaysRun=true) + public void setUp() throws Exception { + managementContext = LocalManagementContextForTests.newInstance(); + } + + @AfterMethod(alwaysRun=true) + public void tearDown() { + if (managementContext != null) Entities.destroyAll(managementContext); + } + + @Test + public void testConfigBagContainsMatchesForConfigKeyName() throws Exception { + LocationInternal loc = managementContext.getLocationManager().createLocation(LocationSpec.create(MyLocation.class) + .configure("mylocation.myconfig", "myval1") + .configure("mylocation.myconfigwithflagname", "myval2")); + + assertEquals(loc.config().getBag().getAllConfig(), ImmutableMap.of("mylocation.myconfig", "myval1", "mylocation.myconfigwithflagname", "myval2")); + assertEquals(loc.config().getLocalBag().getAllConfig(), ImmutableMap.of("mylocation.myconfig", "myval1", "mylocation.myconfigwithflagname", "myval2")); + Assert.assertEquals(loc.getAllConfig(true), ImmutableMap.of("mylocation.myconfig", "myval1", "mylocation.myconfigwithflagname", "myval2")); + Assert.assertEquals(loc.getAllConfig(false), ImmutableMap.of("mylocation.myconfig", "myval1", "mylocation.myconfigwithflagname", "myval2")); + } + + // TODO Note difference compared to Location, where both flag-name + config-key-name are in the ConfigBag + @Test + public void testConfigBagContainsMatchesForFlagName() throws Exception { + // Prefers flag-name, over config-key's name + LocationInternal loc = managementContext.getLocationManager().createLocation(LocationSpec.create(MyLocation.class) + .configure("myconfigflagname", "myval")); + + assertEquals(loc.config().getBag().getAllConfig(), ImmutableMap.of("mylocation.myconfigwithflagname", "myval", "myconfigflagname", "myval")); + assertEquals(loc.config().getLocalBag().getAllConfig(), ImmutableMap.of("mylocation.myconfigwithflagname", "myval", "myconfigflagname", "myval")); + Assert.assertEquals(loc.getAllConfig(true), ImmutableMap.of("mylocation.myconfigwithflagname", "myval", "myconfigflagname", "myval")); + Assert.assertEquals(loc.getAllConfig(false), ImmutableMap.of("mylocation.myconfigwithflagname", "myval", "myconfigflagname", "myval")); + } + + @Test + public void testConfigBagContainsUnmatched() throws Exception { + LocationInternal loc = managementContext.getLocationManager().createLocation(LocationSpec.create(MyLocation.class) + .configure("notThere", "notThereVal")); + + assertEquals(loc.config().getBag().getAllConfig(), ImmutableMap.of("notThere", "notThereVal")); + assertEquals(loc.config().getLocalBag().getAllConfig(), ImmutableMap.of("notThere", "notThereVal")); + Assert.assertEquals(loc.getAllConfig(true), ImmutableMap.of("notThere", "notThereVal")); + Assert.assertEquals(loc.getAllConfig(false), ImmutableMap.of("notThere", "notThereVal")); + } + + // TODO Note difference from entity: child's bag contains both the flag-name and the config-key-name + @Test + public void testChildConfigBagInheritsUnmatchedAtParent() throws Exception { + LocationInternal loc = managementContext.getLocationManager().createLocation(LocationSpec.create(MyLocation.class) + .configure("mychildlocation.myconfig", "myval1") + .configure("notThere", "notThereVal")); + + LocationInternal child = managementContext.getLocationManager().createLocation(LocationSpec.create(MyChildLocation.class) + .parent(loc)); + + assertEquals(child.config().getBag().getAllConfig(), ImmutableMap.of("mychildlocation.myconfig", "myval1", "notThere", "notThereVal")); + assertEquals(child.config().getLocalBag().getAllConfig(), ImmutableMap.of()); + Assert.assertEquals(child.getAllConfig(true), ImmutableMap.of("mychildlocation.myconfig", "myval1", "notThere", "notThereVal")); + Assert.assertEquals(child.getAllConfig(false), ImmutableMap.of()); + } + + // TODO Fails for location, but passes for entity; not worth fixing here; locations will soon be entities! + @Test(groups="WIP") + public void testChildConfigBagInheritsFlagNameFromParentSetsOwnConfigKey() throws Exception { + LocationInternal loc = managementContext.getLocationManager().createLocation(LocationSpec.create(MyLocation.class) + .configure("mychildconfigflagname", "myval")); + + LocationInternal child = managementContext.getLocationManager().createLocation(LocationSpec.create(MyChildLocation.class) + .parent(loc)); + + assertEquals(child.config().getBag().getAllConfig(), ImmutableMap.of("mychildlocation.myconfigwithflagname", "myval")); + assertEquals(child.config().getLocalBag().getAllConfig(), ImmutableMap.of()); + Assert.assertEquals(child.getAllConfig(true), ImmutableMap.of("mychildlocation.myconfigwithflagname", "myval")); + Assert.assertEquals(child.getAllConfig(false), ImmutableMap.of()); + } + + @Test + public void testChildInheritsFromParent() throws Exception { + LocationInternal loc = managementContext.getLocationManager().createLocation(LocationSpec.create(MyLocation.class) + .configure("mylocation.myconfig", "myval1")); + + LocationInternal child = managementContext.getLocationManager().createLocation(LocationSpec.create(MyChildLocation.class) + .parent(loc)); + + assertEquals(child.config().getBag().getAllConfig(), ImmutableMap.of("mylocation.myconfig", "myval1")); + assertEquals(child.config().getLocalBag().getAllConfig(), ImmutableMap.of()); + Assert.assertEquals(child.getAllConfig(true), ImmutableMap.of("mylocation.myconfig", "myval1")); + Assert.assertEquals(child.getAllConfig(false), ImmutableMap.of()); + } + + @Test + public void testChildCanOverrideConfigUsingKeyName() throws Exception { + LocationInternal location = managementContext.getLocationManager().createLocation(LocationSpec.create(MyLocation.class) + .configure("mychildlocation.myconfigwithflagname", "myval") + .configure("notThere", "notThereVal")); + + LocationInternal child = managementContext.getLocationManager().createLocation(LocationSpec.create(MyChildLocation.class) + .parent(location) + .configure("mychildlocation.myconfigwithflagname", "overrideMyval") + .configure("notThere", "overrideNotThereVal")); + + assertEquals(child.config().getBag().getAllConfig(), ImmutableMap.of("mychildlocation.myconfigwithflagname", "overrideMyval", "notThere", "overrideNotThereVal")); + assertEquals(child.config().getLocalBag().getAllConfig(), ImmutableMap.of("mychildlocation.myconfigwithflagname", "overrideMyval", "notThere", "overrideNotThereVal")); + Assert.assertEquals(child.getAllConfig(true), ImmutableMap.of("mychildlocation.myconfigwithflagname", "overrideMyval", "notThere", "overrideNotThereVal")); + Assert.assertEquals(child.getAllConfig(false), ImmutableMap.of("mychildlocation.myconfigwithflagname", "overrideMyval", "notThere", "overrideNotThereVal")); + } + + // TODO Note difference compared to Location, where both flag-name + config-key-name are in the ConfigBag + @Test + public void testChildCanOverrideConfigUsingFlagName() throws Exception { + LocationInternal loc = managementContext.getLocationManager().createLocation(LocationSpec.create(MyLocation.class) + .configure("mychildlocation.myconfigwithflagname", "myval")); + + LocationInternal child = managementContext.getLocationManager().createLocation(LocationSpec.create(MyChildLocation.class) + .parent(loc) + .configure("mychildconfigflagname", "overrideMyval")); + + assertEquals(child.config().getBag().getAllConfig(), ImmutableMap.of("mychildlocation.myconfigwithflagname", "overrideMyval", "mychildconfigflagname", "overrideMyval")); + assertEquals(child.config().getLocalBag().getAllConfig(), ImmutableMap.of("mychildlocation.myconfigwithflagname", "overrideMyval", "mychildconfigflagname", "overrideMyval")); + Assert.assertEquals(child.getAllConfig(true), ImmutableMap.of("mychildlocation.myconfigwithflagname", "overrideMyval", "mychildconfigflagname", "overrideMyval")); + Assert.assertEquals(child.getAllConfig(false), ImmutableMap.of("mychildlocation.myconfigwithflagname", "overrideMyval", "mychildconfigflagname", "overrideMyval")); + } + + @Test + public void testLocationCanOverrideConfigDefaultValue() throws Exception { + LocationInternal loc = managementContext.getLocationManager().createLocation(LocationSpec.create(MyLocation.class)); + LocationInternal subloc = managementContext.getLocationManager().createLocation(LocationSpec.create(MySubLocation.class)); + + Assert.assertEquals(loc.getConfig(MyLocation.MY_CONFIG_WITH_DEFAULT), "mydefault"); + Assert.assertEquals(loc.getConfig(ConfigKeys.newStringConfigKey("mylocation.myconfigwithdefault", "", "differentdefault")), "mydefault"); + + Assert.assertEquals(subloc.getConfig(MySubLocation.MY_CONFIG_WITH_DEFAULT), "mysubdefault"); + Assert.assertEquals(subloc.getConfig(MyLocation.MY_CONFIG_WITH_DEFAULT), "mysubdefault"); + } + + @SuppressWarnings("serial") + public static class MyLocation extends AbstractLocation { + public static final ConfigKey<String> MY_CONFIG = ConfigKeys.newStringConfigKey("mylocation.myconfig"); + + @SetFromFlag("myconfigflagname") + public static final ConfigKey<String> MY_CONFIG_WITH_FLAGNAME = ConfigKeys.newStringConfigKey("mylocation.myconfigwithflagname"); + + public static final ConfigKey<String> MY_CONFIG_WITH_DEFAULT = ConfigKeys.newStringConfigKey("mylocation.myconfigwithdefault", "", "mydefault"); + } + + @SuppressWarnings("serial") + public static class MyChildLocation extends AbstractLocation { + public static final ConfigKey<String> MY_CHILD_CONFIG = ConfigKeys.newStringConfigKey("mychildlocation.myconfig"); + + @SetFromFlag("mychildconfigflagname") + public static final ConfigKey<String> MY_CHILD_CONFIG_WITH_FLAGNAME = ConfigKeys.newStringConfigKey("mychildlocation.myconfigwithflagname"); + } + + @SuppressWarnings("serial") + public static class MySubLocation extends MyLocation { + public static final ConfigKey<String> MY_CONFIG_WITH_DEFAULT = ConfigKeys.newConfigKeyWithDefault(MyLocation.MY_CONFIG_WITH_DEFAULT, "mysubdefault"); + } + +} http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/e2c57058/core/src/test/java/org/apache/brooklyn/location/basic/LocationConfigUtilsTest.java ---------------------------------------------------------------------- diff --git a/core/src/test/java/org/apache/brooklyn/location/basic/LocationConfigUtilsTest.java b/core/src/test/java/org/apache/brooklyn/location/basic/LocationConfigUtilsTest.java new file mode 100644 index 0000000..e9197a1 --- /dev/null +++ b/core/src/test/java/org/apache/brooklyn/location/basic/LocationConfigUtilsTest.java @@ -0,0 +1,155 @@ +/* + * 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.assertTrue; + +import java.io.File; + +import org.testng.Assert; +import org.testng.annotations.Test; + +import brooklyn.util.config.ConfigBag; + +@Test +public class LocationConfigUtilsTest { + + // set these system properties differently if needed to fix your tests + public static final String SSH_PRIVATE_KEY_FILE_WITH_TILDE = System.getProperty("sshPrivateKey", "~/.ssh/id_rsa"); + public static final String SSH_PUBLIC_KEY_FILE_WITH_TILDE = System.getProperty("sshPublicKey", "~/.ssh/id_rsa.pub"); + // these should work as they are on classpath + public static final String SSH_PRIVATE_KEY_FILE_WITH_PASSPHRASE = System.getProperty("sshPrivateKeyWithPassphrase", "/brooklyn/util/crypto/sample_rsa_passphrase.pem"); + public static final String SSH_PRIVATE_KEY_FILE = System.getProperty("sshPrivateKeySample", "/org/apache/brooklyn/location/basic/sample_id_rsa"); + public static final String SSH_PUBLIC_KEY_FILE = System.getProperty("sshPublicKeySample", "/org/apache/brooklyn/location/basic/sample_id_rsa.pub"); + + public void testPreferPrivateKeyDataOverFile() throws Exception { + ConfigBag config = ConfigBag.newInstance(); + config.put(LocationConfigKeys.PRIVATE_KEY_DATA, "mydata"); + config.put(LocationConfigKeys.PRIVATE_KEY_FILE, SSH_PRIVATE_KEY_FILE); + + LocationConfigUtils.OsCredential creds = LocationConfigUtils.getOsCredential(config).doKeyValidation(false); + Assert.assertTrue(creds.hasKey()); + // warnings, as it is malformed + Assert.assertFalse(creds.getWarningMessages().isEmpty()); + + String data = creds.getPrivateKeyData(); + assertEquals(data, "mydata"); + } + + @Test(expectedExceptions=IllegalStateException.class) + public void testInvalidKeyData() throws Exception { + ConfigBag config = ConfigBag.newInstance(); + config.put(LocationConfigKeys.PRIVATE_KEY_DATA, "mydata"); + + LocationConfigUtils.OsCredential creds = LocationConfigUtils.getOsCredential(config).doKeyValidation(false); + Assert.assertTrue(creds.hasKey()); + Assert.assertFalse(creds.getWarningMessages().isEmpty()); + + creds.checkNoErrors(); + } + + public void testPreferPublicKeyDataOverFileAndNoPrivateKeyRequired() throws Exception { + ConfigBag config = ConfigBag.newInstance(); + config.put(LocationConfigKeys.PUBLIC_KEY_DATA, "mydata"); + config.put(LocationConfigKeys.PUBLIC_KEY_FILE, SSH_PUBLIC_KEY_FILE); + config.put(LocationConfigKeys.PRIVATE_KEY_FILE, ""); + + LocationConfigUtils.OsCredential creds = LocationConfigUtils.getOsCredential(config); + String data = creds.getPublicKeyData(); + assertEquals(data, "mydata"); + Assert.assertNull(creds.getPreferredCredential()); + Assert.assertFalse(creds.hasPassword()); + Assert.assertFalse(creds.hasKey()); + // and not even any warnings here + Assert.assertTrue(creds.getWarningMessages().isEmpty()); + } + + @Test(groups="Integration") // requires ~/.ssh/id_rsa + public void testReadsPrivateKeyFileWithTildePath() throws Exception { + ConfigBag config = ConfigBag.newInstance(); + config.put(LocationConfigKeys.PRIVATE_KEY_FILE, SSH_PRIVATE_KEY_FILE_WITH_TILDE); + + // don't mind if it has a passphrase + String data = LocationConfigUtils.getOsCredential(config).doKeyValidation(false).getPreferredCredential(); + assertTrue(data != null && data.length() > 0); + } + + @Test(groups="Integration") + public void testReadsPrivateKeyFileWithPassphrase() throws Exception { + ConfigBag config = ConfigBag.newInstance(); + config.put(LocationConfigKeys.PRIVATE_KEY_FILE, SSH_PRIVATE_KEY_FILE_WITH_PASSPHRASE); + + LocationConfigUtils.OsCredential cred = LocationConfigUtils.getOsCredential(config).doKeyValidation(false); + String data = cred.getPreferredCredential(); + assertTrue(data != null && data.length() > 0); + Assert.assertFalse(data.isEmpty()); + + cred.doKeyValidation(true); + try { + cred.checkNoErrors(); + Assert.fail("check should fail as passphrase needed"); + } catch (IllegalStateException exception) { + } + + config.put(LocationConfigKeys.PRIVATE_KEY_PASSPHRASE, "passphrase"); + cred.checkNoErrors(); + + config.put(LocationConfigKeys.PRIVATE_KEY_PASSPHRASE, "wrong_passphrase"); + try { + cred.checkNoErrors(); + Assert.fail("check should fail as passphrase needed"); + } catch (IllegalStateException exception) { + } + } + + public void testReadsPrivateKeyFileWithMultipleColonSeparatedFilesWithGoodLast() throws Exception { + ConfigBag config = ConfigBag.newInstance(); + config.put(LocationConfigKeys.PRIVATE_KEY_FILE, "/path/does/not/exist"+File.pathSeparator+SSH_PRIVATE_KEY_FILE); + + String data = LocationConfigUtils.getOsCredential(config).getPreferredCredential(); + assertTrue(data != null && data.length() > 0); + } + + public void testReadsPrivateKeyFileWithMultipleColonSeparatedFilesWithGoodFirst() throws Exception { + ConfigBag config = ConfigBag.newInstance(); + config.put(LocationConfigKeys.PRIVATE_KEY_FILE, SSH_PRIVATE_KEY_FILE+File.pathSeparator+"/path/does/not/exist"); + + String data = LocationConfigUtils.getOsCredential(config).getPreferredCredential(); + assertTrue(data != null && data.length() > 0); + } + + @Test(groups="Integration") // requires ~/.ssh/id_rsa + public void testReadsPublicKeyFileWithTildePath() throws Exception { + ConfigBag config = ConfigBag.newInstance(); + config.put(LocationConfigKeys.PUBLIC_KEY_FILE, SSH_PUBLIC_KEY_FILE_WITH_TILDE); + + // don't mind if it has a passphrase + String data = LocationConfigUtils.getOsCredential(config).doKeyValidation(false).getPublicKeyData(); + assertTrue(data != null && data.length() > 0); + } + + public void testInfersPublicKeyFileFromPrivateKeyFile() throws Exception { + ConfigBag config = ConfigBag.newInstance(); + config.put(LocationConfigKeys.PRIVATE_KEY_FILE, SSH_PRIVATE_KEY_FILE); + + String data = LocationConfigUtils.getOsCredential(config).getPublicKeyData(); + assertTrue(data != null && data.length() > 0); + } +}
