Repository: incubator-brooklyn Updated Branches: refs/heads/master 64c6e191a -> 35d75537c
Add YAML port range support Project: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/repo Commit: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/commit/a11a49a2 Tree: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/tree/a11a49a2 Diff: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/diff/a11a49a2 Branch: refs/heads/master Commit: a11a49a28fff6f29beaad6157a6eb9857a2f2674 Parents: 7c649d7 Author: Mike Zaccardo <[email protected]> Authored: Fri Nov 20 11:00:52 2015 -0800 Committer: Mike Zaccardo <[email protected]> Committed: Fri Nov 20 11:00:52 2015 -0800 ---------------------------------------------------------------------- .../brooklyn/core/location/PortRanges.java | 28 +++- .../brooklyn/core/location/PortRangesTest.java | 4 +- .../location/jclouds/JcloudsLocation.java | 64 ++------- .../location/jclouds/JcloudsLocationTest.java | 140 ++++++++++++++++--- .../brooklyn/util/text/StringEscapes.java | 2 +- 5 files changed, 156 insertions(+), 82 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a11a49a2/core/src/main/java/org/apache/brooklyn/core/location/PortRanges.java ---------------------------------------------------------------------- diff --git a/core/src/main/java/org/apache/brooklyn/core/location/PortRanges.java b/core/src/main/java/org/apache/brooklyn/core/location/PortRanges.java index 07daba5..4265e36 100644 --- a/core/src/main/java/org/apache/brooklyn/core/location/PortRanges.java +++ b/core/src/main/java/org/apache/brooklyn/core/location/PortRanges.java @@ -22,7 +22,7 @@ import static com.google.common.base.Preconditions.checkArgument; import java.io.Serializable; import java.util.ArrayList; -import java.util.Collection; +import java.util.Arrays; import java.util.Collections; import java.util.Iterator; import java.util.List; @@ -31,11 +31,13 @@ import java.util.concurrent.atomic.AtomicBoolean; import org.apache.brooklyn.api.location.PortRange; import org.apache.brooklyn.util.core.flags.TypeCoercions; +import org.apache.brooklyn.util.text.StringEscapes.JavaStringEscapes; import com.google.common.base.Function; import com.google.common.base.Objects; import com.google.common.collect.ImmutableList; import com.google.common.collect.Iterables; +import com.google.common.primitives.Ints; public class PortRanges { @@ -188,12 +190,26 @@ public class PortRanges { return new SinglePort(x); } - public static PortRange fromCollection(Collection<?> c) { + public static PortRange fromIterable(Iterable<?> c) { List<PortRange> l = new ArrayList<PortRange>(); for (Object o: c) { if (o instanceof Integer) l.add(fromInteger((Integer)o)); - else if (o instanceof String) l.add(fromString((String)o)); - else if (o instanceof Collection) l.add(fromCollection((Collection<?>)o)); + else if (o instanceof String) + for (String string : JavaStringEscapes.unwrapJsonishListIfPossible((String)o)) + l.add(fromString(string)); + else if (o instanceof Iterable) l.add(fromIterable((Iterable<?>)o)); + else if (o instanceof int[]) l.add(fromIterable(Ints.asList((int[])o))); + else if (o instanceof String[]) + for (String string : (String[])o) + l.add(fromString(string)); + else if (o instanceof Object[]) + for (Object object : (Object[])o) + if (object instanceof Integer) + l.add(fromInteger((Integer)object)); + else if (object instanceof String) + l.add(fromString((String)object)); + else + throw new IllegalArgumentException("'" + object + "' must be of type Integer or String"); else l.add(TypeCoercions.coerce(o, PortRange.class)); } return new AggregatePortRange(l); @@ -243,8 +259,8 @@ public class PortRanges { TypeCoercions.registerAdapter(String.class, PortRange.class, new Function<String,PortRange>() { public PortRange apply(String x) { return fromString(x); } }); - TypeCoercions.registerAdapter(Collection.class, PortRange.class, new Function<Collection,PortRange>() { - public PortRange apply(Collection x) { return fromCollection(x); } + TypeCoercions.registerAdapter(Iterable.class, PortRange.class, new Function<Iterable,PortRange>() { + public PortRange apply(Iterable x) { return fromIterable(x); } }); initialized.set(true); } http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a11a49a2/core/src/test/java/org/apache/brooklyn/core/location/PortRangesTest.java ---------------------------------------------------------------------- diff --git a/core/src/test/java/org/apache/brooklyn/core/location/PortRangesTest.java b/core/src/test/java/org/apache/brooklyn/core/location/PortRangesTest.java index b708169..1c966db 100644 --- a/core/src/test/java/org/apache/brooklyn/core/location/PortRangesTest.java +++ b/core/src/test/java/org/apache/brooklyn/core/location/PortRangesTest.java @@ -40,8 +40,8 @@ public class PortRangesTest { } @Test - public void testFromCollection() { - PortRange r = PortRanges.fromCollection(ImmutableList.of(1234, 2345)); + public void testFromIterable() { + PortRange r = PortRanges.fromIterable(ImmutableList.of(1234, 2345)); assertContents(r, 1234, 2345); } http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a11a49a2/locations/jclouds/src/main/java/org/apache/brooklyn/location/jclouds/JcloudsLocation.java ---------------------------------------------------------------------- diff --git a/locations/jclouds/src/main/java/org/apache/brooklyn/location/jclouds/JcloudsLocation.java b/locations/jclouds/src/main/java/org/apache/brooklyn/location/jclouds/JcloudsLocation.java index 642aafb..2344c71 100644 --- a/locations/jclouds/src/main/java/org/apache/brooklyn/location/jclouds/JcloudsLocation.java +++ b/locations/jclouds/src/main/java/org/apache/brooklyn/location/jclouds/JcloudsLocation.java @@ -24,6 +24,8 @@ import static java.util.concurrent.TimeUnit.SECONDS; import static org.apache.brooklyn.util.JavaGroovyEquivalents.elvis; import static org.apache.brooklyn.util.JavaGroovyEquivalents.groovyTruth; import static org.apache.brooklyn.util.ssh.BashCommands.sbinPath; +import io.cloudsoft.winrm4j.pywinrm.Session; +import io.cloudsoft.winrm4j.pywinrm.WinRMFactory; import java.io.ByteArrayOutputStream; import java.io.File; @@ -56,6 +58,7 @@ import org.apache.brooklyn.api.location.MachineLocation; import org.apache.brooklyn.api.location.MachineLocationCustomizer; import org.apache.brooklyn.api.location.MachineManagementMixins; import org.apache.brooklyn.api.location.NoMachinesAvailableException; +import org.apache.brooklyn.api.location.PortRange; import org.apache.brooklyn.api.mgmt.AccessController; import org.apache.brooklyn.config.ConfigKey; import org.apache.brooklyn.config.ConfigKey.HasConfigKey; @@ -66,6 +69,7 @@ import org.apache.brooklyn.core.location.BasicMachineMetadata; import org.apache.brooklyn.core.location.LocationConfigKeys; import org.apache.brooklyn.core.location.LocationConfigUtils; import org.apache.brooklyn.core.location.LocationConfigUtils.OsCredential; +import org.apache.brooklyn.core.location.PortRanges; import org.apache.brooklyn.core.location.access.PortForwardManager; import org.apache.brooklyn.core.location.access.PortMapping; import org.apache.brooklyn.core.location.cloud.AbstractCloudMachineProvisioningLocation; @@ -115,6 +119,7 @@ import org.apache.brooklyn.util.text.KeyValueParser; import org.apache.brooklyn.util.text.Strings; import org.apache.brooklyn.util.time.Duration; import org.apache.brooklyn.util.time.Time; +import org.apache.commons.lang3.ArrayUtils; import org.jclouds.aws.ec2.compute.AWSEC2TemplateOptions; import org.jclouds.cloudstack.compute.options.CloudStackTemplateOptions; import org.jclouds.compute.ComputeService; @@ -176,9 +181,6 @@ import com.google.common.io.Files; import com.google.common.net.HostAndPort; import com.google.common.primitives.Ints; -import io.cloudsoft.winrm4j.pywinrm.Session; -import io.cloudsoft.winrm4j.pywinrm.WinRMFactory; - /** * For provisioning and managing VMs in a particular provider/region, using jclouds. * Configuration flags are defined in {@link JcloudsLocationConfig}. @@ -1202,7 +1204,7 @@ public class JcloudsLocation extends AbstractCloudMachineProvisioningLocation im }}) .put(INBOUND_PORTS, new CustomizeTemplateOptions() { public void apply(TemplateOptions t, ConfigBag props, Object v) { - int[] inboundPorts = toIntArray(v); + int[] inboundPorts = toIntPortArray(v); if (LOG.isDebugEnabled()) LOG.debug("opening inbound ports {} for cloud/type {}", Arrays.toString(inboundPorts), t.getClass()); t.inboundPorts(inboundPorts); }}) @@ -2926,52 +2928,6 @@ public class JcloudsLocation extends AbstractCloudMachineProvisioningLocation im } } - @VisibleForTesting - static int[] toIntArray(Object v) { - int[] result; - if (v instanceof Iterable) { - result = new int[Iterables.size((Iterable<?>)v)]; - int i = 0; - for (Object o : (Iterable<?>)v) { - result[i++] = (Integer) o; - } - } else if (v instanceof int[]) { - result = (int[]) v; - } else if (v instanceof Object[]) { - result = new int[((Object[])v).length]; - for (int i = 0; i < result.length; i++) { - result[i] = (Integer) ((Object[])v)[i]; - } - } else if (v instanceof Integer) { - result = new int[] {(Integer)v}; - } else if (v instanceof String) { - Matcher listMatcher = LIST_PATTERN.matcher(v.toString()); - boolean intList = true; - if (listMatcher.matches()) { - List<String> strings = KeyValueParser.parseList(listMatcher.group(1)); - List<Integer> integers = new ArrayList<Integer>(); - for (String string : strings) { - if (INTEGER_PATTERN.matcher(string).matches()) { - integers.add(Integer.parseInt(string)); - } else { - intList = false; - break; - } - } - result = Ints.toArray(integers); - } else { - intList = false; - result = null; - } - if (!intList) { - throw new IllegalArgumentException("Invalid type for int[]: "+v+" of type "+v.getClass()); - } - } else { - throw new IllegalArgumentException("Invalid type for int[]: "+v+" of type "+v.getClass()); - } - return result; - } - protected static String[] toStringArray(Object v) { return toListOfStrings(v).toArray(new String[0]); } @@ -3004,6 +2960,14 @@ public class JcloudsLocation extends AbstractCloudMachineProvisioningLocation im } } + @VisibleForTesting + static int[] toIntPortArray(Object v) { + PortRange portRange = PortRanges.fromIterable(Collections.singletonList(v)); + int[] portArray = ArrayUtils.toPrimitive(Iterables.toArray(portRange, Integer.class)); + + return portArray; + } + // Handles GString protected static Map<String,String> toMapStringString(Object v) { if (v instanceof Map<?,?>) { http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a11a49a2/locations/jclouds/src/test/java/org/apache/brooklyn/location/jclouds/JcloudsLocationTest.java ---------------------------------------------------------------------- diff --git a/locations/jclouds/src/test/java/org/apache/brooklyn/location/jclouds/JcloudsLocationTest.java b/locations/jclouds/src/test/java/org/apache/brooklyn/location/jclouds/JcloudsLocationTest.java index b4aeb17..851505d 100644 --- a/locations/jclouds/src/test/java/org/apache/brooklyn/location/jclouds/JcloudsLocationTest.java +++ b/locations/jclouds/src/test/java/org/apache/brooklyn/location/jclouds/JcloudsLocationTest.java @@ -18,6 +18,7 @@ */ package org.apache.brooklyn.location.jclouds; +import java.util.Collection; import java.util.Map; import java.util.concurrent.CountDownLatch; import java.util.concurrent.ExecutorService; @@ -40,6 +41,7 @@ import org.apache.brooklyn.core.location.cloud.names.CustomMachineNamer; import org.apache.brooklyn.core.location.geo.HostGeoInfo; import org.apache.brooklyn.core.mgmt.internal.LocalManagementContext; import org.apache.brooklyn.core.test.entity.LocalManagementContextForTests; +import org.apache.brooklyn.location.jclouds.JcloudsLocation.UserCreation; import org.apache.brooklyn.test.Asserts; import org.apache.brooklyn.util.collections.MutableMap; import org.apache.brooklyn.util.core.config.ConfigBag; @@ -56,12 +58,15 @@ import org.testng.annotations.Test; import com.google.common.base.Function; import com.google.common.base.Predicate; +import com.google.common.collect.ContiguousSet; +import com.google.common.collect.DiscreteDomain; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; +import com.google.common.collect.Lists; +import com.google.common.collect.Range; +import com.google.common.primitives.Ints; import com.google.common.reflect.TypeToken; -import org.apache.brooklyn.location.jclouds.JcloudsLocation.UserCreation; - /** * @author Shane Witbeck */ @@ -102,7 +107,7 @@ public class JcloudsLocationTest implements JcloudsLocationConfig { public void tearUp() throws Exception { if (managementContext != null) Entities.destroyAll(managementContext); } - + @Test public void testCreateWithFlagsDirectly() throws Exception { BailOutJcloudsLocation jcl = BailOutJcloudsLocation.newBailOutJcloudsLocation(managementContext); @@ -123,42 +128,131 @@ public class JcloudsLocationTest implements JcloudsLocationConfig { } @Test - public void testStringListToIntArray() { + public void testSingleInttoIntPortArray() { + int port = 1; + int[] intArray = new int[] {1}; + Assert.assertEquals(JcloudsLocation.toIntPortArray(port), intArray); + } + + @Test + public void testSingleStringtoIntPortArray() { + String portString = "1"; + int[] intArray = new int[] {1}; + Assert.assertEquals(JcloudsLocation.toIntPortArray(portString), intArray); + } + + @Test + public void testStringListWithBracketstoIntPortArray() { String listString = "[1, 2, 3, 4]"; int[] intArray = new int[] {1, 2, 3, 4}; - Assert.assertEquals(JcloudsLocation.toIntArray(listString), intArray); + Assert.assertEquals(JcloudsLocation.toIntPortArray(listString), intArray); } - - @Test(expectedExceptions = IllegalArgumentException.class) - public void testMalformedStringListToIntArray() { + + @Test + public void testStringListWithoutBracketstoIntPortArray() { String listString = "1, 2, 3, 4"; - JcloudsLocation.toIntArray(listString); + int[] intArray = new int[] {1, 2, 3, 4}; + Assert.assertEquals(JcloudsLocation.toIntPortArray(listString), intArray); } - + @Test - public void testEmptyStringListToIntArray() { + public void testEmptyStringListtoIntPortArray() { String listString = "[]"; int[] intArray = new int[] {}; - Assert.assertEquals(JcloudsLocation.toIntArray(listString), intArray); + Assert.assertEquals(JcloudsLocation.toIntPortArray(listString), intArray); } - + @Test - public void testIntArrayToIntArray() { + public void testIntArraytoIntPortArray() { int[] intArray = new int[] {1, 2, 3, 4}; - Assert.assertEquals(JcloudsLocation.toIntArray(intArray), intArray); + Assert.assertEquals(JcloudsLocation.toIntPortArray(intArray), intArray); } - + @Test - public void testObjectArrayToIntArray() { - Object[] longArray = new Object[] {1, 2, 3, 4}; + public void testObjectArrayOfIntegerstoIntPortArray() { + Object[] integerObjectArray = new Object[] {1, 2, 3, 4}; int[] intArray = new int[] {1, 2, 3, 4}; - Assert.assertEquals(JcloudsLocation.toIntArray(longArray), intArray); + Assert.assertEquals(JcloudsLocation.toIntPortArray(integerObjectArray), intArray); } - - @Test(expectedExceptions = ClassCastException.class) - public void testInvalidObjectArrayToIntArray() { + + @Test + public void testObjectArrayOfStringstoIntPortArray() { + Object[] stringObjectArray = new Object[] {"1", "2", "3", "4"}; + int[] intArray = new int[] {1, 2, 3, 4}; + Assert.assertEquals(JcloudsLocation.toIntPortArray(stringObjectArray), intArray); + } + + @Test + public void testStringArraytoIntPortArray() { String[] stringArray = new String[] {"1", "2", "3"}; - JcloudsLocation.toIntArray(stringArray); + int[] intArray = new int[] {1, 2, 3}; + Assert.assertEquals(JcloudsLocation.toIntPortArray(stringArray), intArray); + } + + @Test + public void testStringPortRangetoIntPortArray() { + String portRange = "1-100"; + int[] intArray = Ints.toArray(ContiguousSet.create(Range.closed(1, 100), DiscreteDomain.integers())); + Assert.assertEquals(intArray, JcloudsLocation.toIntPortArray(portRange)); + } + + @Test + public void testStringPortPlustoIntPortArray() { + String portPlus = "100+"; + int[] intArray = Ints.toArray(ContiguousSet.create(Range.closed(100, 65535), DiscreteDomain.integers())); + Assert.assertEquals(intArray, JcloudsLocation.toIntPortArray(portPlus)); + } + + @Test + public void testCombinationOfInputstoIntPortArray() { + Collection<Object> portInputs = Lists.newLinkedList(); + portInputs.add(1); + portInputs.add("2"); + portInputs.add("3-100"); + portInputs.add("101,102,103"); + portInputs.add("[104,105,106]"); + portInputs.add(new int[] {107, 108, 109}); + portInputs.add(new String[] {"110", "111", "112"}); + portInputs.add(new Object[] {113, 114, 115}); + + int[] intArray = Ints.toArray(ContiguousSet.create(Range.closed(1, 115), DiscreteDomain.integers())); + Assert.assertEquals(intArray, JcloudsLocation.toIntPortArray(portInputs)); + } + + @Test(expectedExceptions = IllegalArgumentException.class) + public void testMalformedStringNumbertoIntPortArray() { + String numberStr = "1i"; + JcloudsLocation.toIntPortArray(numberStr); + } + + @Test(expectedExceptions = IllegalArgumentException.class) + public void testMalformedStringRangetoIntPortArray() { + String rangeString = "1-"; + JcloudsLocation.toIntPortArray(rangeString); + } + + @Test(expectedExceptions = IllegalArgumentException.class) + public void testMalformedStringListWithBracketstoIntPortArray() { + String listString = "[1,2,e]"; + JcloudsLocation.toIntPortArray(listString); + } + + @Test(expectedExceptions = IllegalArgumentException.class) + public void testMalformedStringListWithoutBracketstoIntPortArray() { + String listString = "1,2,e"; + JcloudsLocation.toIntPortArray(listString); + } + + @Test(expectedExceptions = IllegalArgumentException.class) + public void testMalformedStringArraytoIntPortArray() { + String[] stringArray = new String[] {"1", "2", "e"}; + JcloudsLocation.toIntPortArray(stringArray); + } + + @Test(expectedExceptions = IllegalArgumentException.class) + public void testIllegalObjectArrayOfDoublestoIntPortArray() { + Object[] doubleObjectArray = new Object[] {1.0, 2.0, 3.0}; + JcloudsLocation.toIntPortArray(doubleObjectArray); } @Test http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a11a49a2/utils/common/src/main/java/org/apache/brooklyn/util/text/StringEscapes.java ---------------------------------------------------------------------- diff --git a/utils/common/src/main/java/org/apache/brooklyn/util/text/StringEscapes.java b/utils/common/src/main/java/org/apache/brooklyn/util/text/StringEscapes.java index b835e12..f713ff6 100644 --- a/utils/common/src/main/java/org/apache/brooklyn/util/text/StringEscapes.java +++ b/utils/common/src/main/java/org/apache/brooklyn/util/text/StringEscapes.java @@ -362,7 +362,7 @@ public class StringEscapes { String i1 = input.trim(); boolean inBrackets = (i1.startsWith("[") && i1.endsWith("]")); - if (inBrackets) i1 = i1.substring(1, i1.length()-2).trim(); + if (inBrackets) i1 = i1.substring(1, i1.length()-1).trim(); QuotedStringTokenizer qst = new QuotedStringTokenizer(i1, "\"", true, ",", false); while (qst.hasMoreTokens()) {
