mirror of https://github.com/apache/jclouds.git
updated ec2 to support instances without a keypair to exist and not break computeservice
This commit is contained in:
parent
3e39324e90
commit
82bb9e98f7
|
@ -72,4 +72,9 @@ public class RegionTag {
|
||||||
return tag;
|
return tag;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "RegionTag [region=" + region + ", tag=" + tag + "]";
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,6 +19,7 @@
|
||||||
package org.jclouds.aws.ec2.compute.functions;
|
package org.jclouds.aws.ec2.compute.functions;
|
||||||
|
|
||||||
import static com.google.common.base.Preconditions.checkNotNull;
|
import static com.google.common.base.Preconditions.checkNotNull;
|
||||||
|
import static org.jclouds.util.Utils.nullSafeSet;
|
||||||
|
|
||||||
import java.net.InetAddress;
|
import java.net.InetAddress;
|
||||||
import java.net.URI;
|
import java.net.URI;
|
||||||
|
@ -28,7 +29,6 @@ import java.util.Set;
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
import javax.inject.Singleton;
|
import javax.inject.Singleton;
|
||||||
|
|
||||||
import com.google.common.collect.Maps;
|
|
||||||
import org.jclouds.aws.ec2.compute.domain.RegionTag;
|
import org.jclouds.aws.ec2.compute.domain.RegionTag;
|
||||||
import org.jclouds.aws.ec2.domain.Image;
|
import org.jclouds.aws.ec2.domain.Image;
|
||||||
import org.jclouds.aws.ec2.domain.InstanceState;
|
import org.jclouds.aws.ec2.domain.InstanceState;
|
||||||
|
@ -46,8 +46,8 @@ import org.jclouds.domain.Credentials;
|
||||||
import com.google.common.annotations.VisibleForTesting;
|
import com.google.common.annotations.VisibleForTesting;
|
||||||
import com.google.common.base.Function;
|
import com.google.common.base.Function;
|
||||||
import com.google.common.collect.ImmutableMap;
|
import com.google.common.collect.ImmutableMap;
|
||||||
import com.google.common.collect.ImmutableSet;
|
|
||||||
import com.google.common.collect.Iterables;
|
import com.google.common.collect.Iterables;
|
||||||
|
import com.google.common.collect.Maps;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Adrian Cole
|
* @author Adrian Cole
|
||||||
|
@ -76,16 +76,23 @@ public class RunningInstanceToNodeMetadata implements Function<RunningInstance,
|
||||||
String id = checkNotNull(instance, "instance").getId();
|
String id = checkNotNull(instance, "instance").getId();
|
||||||
String name = null; // user doesn't determine a node name;
|
String name = null; // user doesn't determine a node name;
|
||||||
URI uri = null; // no uri to get rest access to host info
|
URI uri = null; // no uri to get rest access to host info
|
||||||
|
|
||||||
|
Credentials credentials = null;// default if no keypair exists
|
||||||
|
String tag = String.format("NOTAG-%s", instance.getId());// default if no keypair exists
|
||||||
|
|
||||||
|
if (instance.getKeyName() != null) {
|
||||||
|
tag = instance.getKeyName().replaceAll("-[0-9]+", "");
|
||||||
|
credentials = new Credentials(getLoginAccountFor(instance), getPrivateKeyOrNull(instance,
|
||||||
|
tag));
|
||||||
|
}
|
||||||
|
|
||||||
Map<String, String> userMetadata = ImmutableMap.<String, String> of();
|
Map<String, String> userMetadata = ImmutableMap.<String, String> of();
|
||||||
String tag = instance.getKeyName().replaceAll("-[0-9]+", "");
|
|
||||||
NodeState state = instanceToNodeState.get(instance.getInstanceState());
|
NodeState state = instanceToNodeState.get(instance.getInstanceState());
|
||||||
|
|
||||||
Set<InetAddress> publicAddresses = nullSafeSet(instance.getIpAddress());
|
Set<InetAddress> publicAddresses = nullSafeSet(instance.getIpAddress());
|
||||||
Set<InetAddress> privateAddresses = nullSafeSet(instance.getPrivateIpAddress());
|
Set<InetAddress> privateAddresses = nullSafeSet(instance.getPrivateIpAddress());
|
||||||
|
|
||||||
Credentials credentials = new Credentials(getLoginAccountFor(instance), getPrivateKeyOrNull(
|
|
||||||
instance, tag));
|
|
||||||
|
|
||||||
String locationId = instance.getAvailabilityZone().toString();
|
String locationId = instance.getAvailabilityZone().toString();
|
||||||
|
|
||||||
Map<String, String> extra = getExtra(instance);
|
Map<String, String> extra = getExtra(instance);
|
||||||
|
@ -94,25 +101,25 @@ public class RunningInstanceToNodeMetadata implements Function<RunningInstance,
|
||||||
publicAddresses, privateAddresses, extra, credentials);
|
publicAddresses, privateAddresses, extra, credentials);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set extras for the node.
|
* Set extras for the node.
|
||||||
*
|
*
|
||||||
* Extras are derived from either additional API calls or
|
* Extras are derived from either additional API calls or hard-coded values.
|
||||||
* hard-coded values.
|
*
|
||||||
* @param instance instance for which the extras are retrieved
|
* @param instance
|
||||||
* @return map with extras
|
* instance for which the extras are retrieved
|
||||||
*/
|
* @return map with extras
|
||||||
|
*/
|
||||||
@VisibleForTesting
|
@VisibleForTesting
|
||||||
Map<String, String> getExtra(RunningInstance instance) {
|
Map<String, String> getExtra(RunningInstance instance) {
|
||||||
Map<String, String> extra = Maps.newHashMap();
|
Map<String, String> extra = Maps.newHashMap();
|
||||||
|
|
||||||
//put storage info
|
// put storage info
|
||||||
/* TODO: only valid for UNIX */
|
/* TODO: only valid for UNIX */
|
||||||
InstanceTypeToStorageMappingUnix instanceToStorageMapping =
|
InstanceTypeToStorageMappingUnix instanceToStorageMapping = new InstanceTypeToStorageMappingUnix();
|
||||||
new InstanceTypeToStorageMappingUnix();
|
extra.putAll(instanceToStorageMapping.apply(instance.getInstanceType()));
|
||||||
extra.putAll(instanceToStorageMapping.apply(instance.getInstanceType()));
|
|
||||||
|
|
||||||
return extra;
|
return extra;
|
||||||
}
|
}
|
||||||
|
|
||||||
@VisibleForTesting
|
@VisibleForTesting
|
||||||
|
@ -131,11 +138,4 @@ public class RunningInstanceToNodeMetadata implements Function<RunningInstance,
|
||||||
+ from.getImageId()).account;
|
+ from.getImageId()).account;
|
||||||
}
|
}
|
||||||
|
|
||||||
Set<InetAddress> nullSafeSet(InetAddress in) {
|
|
||||||
if (in == null) {
|
|
||||||
return ImmutableSet.<InetAddress> of();
|
|
||||||
}
|
|
||||||
return ImmutableSet.<InetAddress> of(in);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
|
@ -55,7 +55,7 @@ public interface AMIClient {
|
||||||
* />
|
* />
|
||||||
* @see DescribeImagesOptions
|
* @see DescribeImagesOptions
|
||||||
*/
|
*/
|
||||||
@Timeout(duration = 180, timeUnit = TimeUnit.SECONDS)
|
@Timeout(duration = 300, timeUnit = TimeUnit.SECONDS)
|
||||||
Set<Image> describeImagesInRegion(Region region, DescribeImagesOptions... options);
|
Set<Image> describeImagesInRegion(Region region, DescribeImagesOptions... options);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -42,7 +42,7 @@ import com.google.common.collect.Iterables;
|
||||||
/**
|
/**
|
||||||
* @author Adrian Cole
|
* @author Adrian Cole
|
||||||
*/
|
*/
|
||||||
@Test(groups = "unit", testName = "compute.PropertiesTest")
|
@Test(groups = "unit", testName = "compute.ImageParserTest")
|
||||||
public class ImageParserTest extends BaseHandlerTest {
|
public class ImageParserTest extends BaseHandlerTest {
|
||||||
|
|
||||||
public void testParseAlesticCanonicalImage() {
|
public void testParseAlesticCanonicalImage() {
|
||||||
|
|
|
@ -0,0 +1,150 @@
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* Copyright (C) 2009 Cloud Conscious, LLC. <info@cloudconscious.com>
|
||||||
|
*
|
||||||
|
* ====================================================================
|
||||||
|
* Licensed 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.jclouds.aws.ec2.compute.functions;
|
||||||
|
|
||||||
|
import static org.easymock.EasyMock.expect;
|
||||||
|
import static org.easymock.classextension.EasyMock.createMock;
|
||||||
|
import static org.easymock.classextension.EasyMock.replay;
|
||||||
|
import static org.easymock.classextension.EasyMock.verify;
|
||||||
|
import static org.jclouds.aws.ec2.options.DescribeImagesOptions.Builder.imageIds;
|
||||||
|
import static org.testng.Assert.assertEquals;
|
||||||
|
|
||||||
|
import java.net.InetAddress;
|
||||||
|
import java.net.UnknownHostException;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import org.jclouds.aws.domain.Region;
|
||||||
|
import org.jclouds.aws.ec2.compute.domain.RegionTag;
|
||||||
|
import org.jclouds.aws.ec2.domain.AvailabilityZone;
|
||||||
|
import org.jclouds.aws.ec2.domain.Image;
|
||||||
|
import org.jclouds.aws.ec2.domain.InstanceState;
|
||||||
|
import org.jclouds.aws.ec2.domain.InstanceType;
|
||||||
|
import org.jclouds.aws.ec2.domain.KeyPair;
|
||||||
|
import org.jclouds.aws.ec2.domain.RunningInstance;
|
||||||
|
import org.jclouds.aws.ec2.services.AMIClient;
|
||||||
|
import org.jclouds.compute.domain.NodeMetadata;
|
||||||
|
import org.jclouds.compute.strategy.PopulateDefaultLoginCredentialsForImageStrategy;
|
||||||
|
import org.jclouds.domain.Credentials;
|
||||||
|
import org.testng.annotations.Test;
|
||||||
|
|
||||||
|
import com.google.common.collect.ImmutableSet;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Adrian Cole
|
||||||
|
*/
|
||||||
|
@Test(groups = "unit", testName = "ec2.RunningInstanceToNodeMetadataTest")
|
||||||
|
public class RunningInstanceToNodeMetadataTest {
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
@Test
|
||||||
|
public void testApplyWithNoKeyPairCreatesTagOfIdPrefixedByTagAndNullCredentials()
|
||||||
|
throws UnknownHostException {
|
||||||
|
AMIClient amiClient = createMock(AMIClient.class);
|
||||||
|
Map<RegionTag, KeyPair> credentialsMap = createMock(Map.class);
|
||||||
|
PopulateDefaultLoginCredentialsForImageStrategy credentialProvider = createMock(PopulateDefaultLoginCredentialsForImageStrategy.class);
|
||||||
|
RunningInstance instance = createMock(RunningInstance.class);
|
||||||
|
|
||||||
|
expect(instance.getId()).andReturn("id").atLeastOnce();
|
||||||
|
expect(instance.getKeyName()).andReturn(null).atLeastOnce();
|
||||||
|
expect(instance.getInstanceState()).andReturn(InstanceState.RUNNING);
|
||||||
|
|
||||||
|
expect(instance.getIpAddress()).andReturn(
|
||||||
|
InetAddress.getByAddress(new byte[] { 12, 10, 10, 1 }));
|
||||||
|
expect(instance.getPrivateIpAddress()).andReturn(
|
||||||
|
InetAddress.getByAddress(new byte[] { 10, 10, 10, 1 }));
|
||||||
|
|
||||||
|
expect(instance.getAvailabilityZone()).andReturn(AvailabilityZone.US_EAST_1A).atLeastOnce();
|
||||||
|
|
||||||
|
expect(instance.getInstanceType()).andReturn(InstanceType.C1_XLARGE).atLeastOnce();
|
||||||
|
|
||||||
|
replay(amiClient);
|
||||||
|
replay(credentialsMap);
|
||||||
|
replay(credentialProvider);
|
||||||
|
replay(instance);
|
||||||
|
|
||||||
|
RunningInstanceToNodeMetadata parser = new RunningInstanceToNodeMetadata(amiClient,
|
||||||
|
credentialsMap, credentialProvider);
|
||||||
|
|
||||||
|
NodeMetadata metadata = parser.apply(instance);
|
||||||
|
|
||||||
|
assertEquals(metadata.getTag(), "NOTAG-id");
|
||||||
|
assertEquals(metadata.getCredentials(), null);
|
||||||
|
|
||||||
|
verify(amiClient);
|
||||||
|
verify(credentialsMap);
|
||||||
|
verify(credentialProvider);
|
||||||
|
verify(instance);
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
@Test
|
||||||
|
public void testApplyWithKeyPairCreatesTagOfParsedKeyPairAndCredentialsBasedOnIt()
|
||||||
|
throws UnknownHostException {
|
||||||
|
AMIClient amiClient = createMock(AMIClient.class);
|
||||||
|
Map<RegionTag, KeyPair> credentialsMap = createMock(Map.class);
|
||||||
|
PopulateDefaultLoginCredentialsForImageStrategy credentialProvider = createMock(PopulateDefaultLoginCredentialsForImageStrategy.class);
|
||||||
|
RunningInstance instance = createMock(RunningInstance.class);
|
||||||
|
Image image = createMock(Image.class);
|
||||||
|
|
||||||
|
expect(instance.getId()).andReturn("id").atLeastOnce();
|
||||||
|
expect(instance.getKeyName()).andReturn("keyName-100").atLeastOnce();
|
||||||
|
expect(instance.getInstanceState()).andReturn(InstanceState.RUNNING);
|
||||||
|
|
||||||
|
expect(instance.getIpAddress()).andReturn(
|
||||||
|
InetAddress.getByAddress(new byte[] { 12, 10, 10, 1 }));
|
||||||
|
expect(instance.getPrivateIpAddress()).andReturn(
|
||||||
|
InetAddress.getByAddress(new byte[] { 10, 10, 10, 1 }));
|
||||||
|
|
||||||
|
expect(instance.getRegion()).andReturn(Region.US_EAST_1).atLeastOnce();
|
||||||
|
|
||||||
|
expect(instance.getImageId()).andReturn("imageId").atLeastOnce();
|
||||||
|
|
||||||
|
expect(amiClient.describeImagesInRegion(Region.US_EAST_1, imageIds("imageId"))).andReturn(
|
||||||
|
ImmutableSet.<Image> of(image));
|
||||||
|
|
||||||
|
expect(credentialProvider.execute(image)).andReturn(new Credentials("user", "pass"));
|
||||||
|
|
||||||
|
expect(credentialsMap.get(new RegionTag(Region.US_EAST_1, "keyName-100"))).andReturn(
|
||||||
|
new KeyPair(Region.US_EAST_1, "keyName-100", "keyFingerprint", "pass"));
|
||||||
|
|
||||||
|
expect(instance.getAvailabilityZone()).andReturn(AvailabilityZone.US_EAST_1A).atLeastOnce();
|
||||||
|
|
||||||
|
expect(instance.getInstanceType()).andReturn(InstanceType.C1_XLARGE).atLeastOnce();
|
||||||
|
|
||||||
|
replay(amiClient);
|
||||||
|
replay(credentialsMap);
|
||||||
|
replay(credentialProvider);
|
||||||
|
replay(instance);
|
||||||
|
|
||||||
|
RunningInstanceToNodeMetadata parser = new RunningInstanceToNodeMetadata(amiClient,
|
||||||
|
credentialsMap, credentialProvider);
|
||||||
|
|
||||||
|
NodeMetadata metadata = parser.apply(instance);
|
||||||
|
|
||||||
|
assertEquals(metadata.getTag(), "keyName");
|
||||||
|
|
||||||
|
assertEquals(metadata.getCredentials(), new Credentials("user", "pass"));
|
||||||
|
|
||||||
|
verify(amiClient);
|
||||||
|
verify(credentialsMap);
|
||||||
|
verify(credentialProvider);
|
||||||
|
verify(instance);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -304,16 +304,20 @@ public abstract class BaseComputeServiceLiveTest {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testGetNodesWithDetails() throws Exception {
|
public void testGetNodesWithDetails() throws Exception {
|
||||||
for (Entry<String, ? extends ComputeMetadata> node : client.getNodes(new GetNodesOptions().withDetails()).entrySet()) {
|
for (Entry<String, ? extends ComputeMetadata> node : client.getNodes(
|
||||||
|
new GetNodesOptions().withDetails()).entrySet()) {
|
||||||
assertEquals(node.getKey(), node.getValue().getId());
|
assertEquals(node.getKey(), node.getValue().getId());
|
||||||
assert node.getValue().getId() != null;
|
assert node.getValue().getId() != null : node;
|
||||||
assert node.getValue().getLocationId() != null;
|
assert node.getValue().getLocationId() != null : node;
|
||||||
assertEquals(node.getValue().getType(), ComputeType.NODE);
|
assertEquals(node.getValue().getType(), ComputeType.NODE);
|
||||||
assert node.getValue() instanceof NodeMetadata;
|
assert node.getValue() instanceof NodeMetadata;
|
||||||
NodeMetadata nodeMetadata = (NodeMetadata)node.getValue();
|
NodeMetadata nodeMetadata = (NodeMetadata) node.getValue();
|
||||||
assertNotNull(nodeMetadata.getName());
|
assert nodeMetadata.getId() != null : nodeMetadata;
|
||||||
assertNotNull(nodeMetadata.getPublicAddresses());
|
// user specified name is not always supported
|
||||||
assert nodeMetadata.getPublicAddresses().size() > 1;
|
// assert nodeMetadata.getName() != null : nodeMetadata;
|
||||||
|
assert nodeMetadata.getPublicAddresses() != null : nodeMetadata;
|
||||||
|
|
||||||
|
assert nodeMetadata.getPublicAddresses().size() > 1 : nodeMetadata;
|
||||||
assertNotNull(nodeMetadata.getPrivateAddresses());
|
assertNotNull(nodeMetadata.getPrivateAddresses());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -96,4 +96,66 @@ public class BaseHttpRequestOptions implements HttpRequestOptions {
|
||||||
return formParameters;
|
return formParameters;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
final int prime = 31;
|
||||||
|
int result = 1;
|
||||||
|
result = prime * result + ((formParameters == null) ? 0 : formParameters.hashCode());
|
||||||
|
result = prime * result + ((headers == null) ? 0 : headers.hashCode());
|
||||||
|
result = prime * result + ((matrixParameters == null) ? 0 : matrixParameters.hashCode());
|
||||||
|
result = prime * result + ((pathSuffix == null) ? 0 : pathSuffix.hashCode());
|
||||||
|
result = prime * result + ((payload == null) ? 0 : payload.hashCode());
|
||||||
|
result = prime * result + ((queryParameters == null) ? 0 : queryParameters.hashCode());
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object obj) {
|
||||||
|
if (this == obj)
|
||||||
|
return true;
|
||||||
|
if (obj == null)
|
||||||
|
return false;
|
||||||
|
if (getClass() != obj.getClass())
|
||||||
|
return false;
|
||||||
|
BaseHttpRequestOptions other = (BaseHttpRequestOptions) obj;
|
||||||
|
if (formParameters == null) {
|
||||||
|
if (other.formParameters != null)
|
||||||
|
return false;
|
||||||
|
} else if (!formParameters.equals(other.formParameters))
|
||||||
|
return false;
|
||||||
|
if (headers == null) {
|
||||||
|
if (other.headers != null)
|
||||||
|
return false;
|
||||||
|
} else if (!headers.equals(other.headers))
|
||||||
|
return false;
|
||||||
|
if (matrixParameters == null) {
|
||||||
|
if (other.matrixParameters != null)
|
||||||
|
return false;
|
||||||
|
} else if (!matrixParameters.equals(other.matrixParameters))
|
||||||
|
return false;
|
||||||
|
if (pathSuffix == null) {
|
||||||
|
if (other.pathSuffix != null)
|
||||||
|
return false;
|
||||||
|
} else if (!pathSuffix.equals(other.pathSuffix))
|
||||||
|
return false;
|
||||||
|
if (payload == null) {
|
||||||
|
if (other.payload != null)
|
||||||
|
return false;
|
||||||
|
} else if (!payload.equals(other.payload))
|
||||||
|
return false;
|
||||||
|
if (queryParameters == null) {
|
||||||
|
if (other.queryParameters != null)
|
||||||
|
return false;
|
||||||
|
} else if (!queryParameters.equals(other.queryParameters))
|
||||||
|
return false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "[formParameters=" + formParameters + ", headers=" + headers + ", matrixParameters="
|
||||||
|
+ matrixParameters + ", pathSuffix=" + pathSuffix + ", payload=" + payload
|
||||||
|
+ ", queryParameters=" + queryParameters + "]";
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
|
@ -29,6 +29,7 @@ import java.io.OutputStream;
|
||||||
import java.io.UnsupportedEncodingException;
|
import java.io.UnsupportedEncodingException;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
import java.util.Map.Entry;
|
import java.util.Map.Entry;
|
||||||
import java.util.regex.Matcher;
|
import java.util.regex.Matcher;
|
||||||
import java.util.regex.Pattern;
|
import java.util.regex.Pattern;
|
||||||
|
@ -40,187 +41,195 @@ import org.jclouds.logging.Logger;
|
||||||
import com.google.common.base.Charsets;
|
import com.google.common.base.Charsets;
|
||||||
import com.google.common.base.Supplier;
|
import com.google.common.base.Supplier;
|
||||||
import com.google.common.base.Throwables;
|
import com.google.common.base.Throwables;
|
||||||
|
import com.google.common.collect.ImmutableSet;
|
||||||
import com.google.common.io.ByteStreams;
|
import com.google.common.io.ByteStreams;
|
||||||
import com.google.common.io.Closeables;
|
import com.google.common.io.Closeables;
|
||||||
import com.google.common.io.OutputSupplier;
|
import com.google.common.io.OutputSupplier;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* General utilities used in jclouds code.
|
* General utilities used in jclouds code.
|
||||||
*
|
*
|
||||||
* @author Adrian Cole
|
* @author Adrian Cole
|
||||||
*/
|
*/
|
||||||
public class Utils {
|
public class Utils {
|
||||||
public static final String UTF8_ENCODING = "UTF-8";
|
public static final String UTF8_ENCODING = "UTF-8";
|
||||||
|
|
||||||
public static Object propagateOrNull(Exception from) {
|
public static <T> Set<T> nullSafeSet(T in) {
|
||||||
Throwables.propagate(from);
|
if (in == null) {
|
||||||
assert false : "exception should have propogated";
|
return ImmutableSet.<T> of();
|
||||||
return null;
|
}
|
||||||
}
|
return ImmutableSet.<T> of(in);
|
||||||
|
}
|
||||||
|
|
||||||
public static String replaceTokens(String value, Collection<Entry<String, String>> tokenValues) {
|
public static Object propagateOrNull(Exception from) {
|
||||||
for (Entry<String, String> tokenValue : tokenValues) {
|
Throwables.propagate(from);
|
||||||
value = replaceAll(value, TOKEN_TO_PATTERN.get(tokenValue.getKey()), tokenValue.getValue());
|
assert false : "exception should have propogated";
|
||||||
}
|
return null;
|
||||||
return value;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
public static String replaceAll(String returnVal, Pattern pattern, String replace) {
|
public static String replaceTokens(String value, Collection<Entry<String, String>> tokenValues) {
|
||||||
Matcher m = pattern.matcher(returnVal);
|
for (Entry<String, String> tokenValue : tokenValues) {
|
||||||
returnVal = m.replaceAll(replace);
|
value = replaceAll(value, TOKEN_TO_PATTERN.get(tokenValue.getKey()), tokenValue.getValue());
|
||||||
return returnVal;
|
}
|
||||||
}
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
public static String replaceAll(String input, char ifMatch, Pattern pattern, String replacement) {
|
public static String replaceAll(String returnVal, Pattern pattern, String replace) {
|
||||||
if (input.indexOf(ifMatch) != -1) {
|
Matcher m = pattern.matcher(returnVal);
|
||||||
input = pattern.matcher(input).replaceAll(replacement);
|
returnVal = m.replaceAll(replace);
|
||||||
}
|
return returnVal;
|
||||||
return input;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
public static String replaceAll(String input, char match, String replacement) {
|
public static String replaceAll(String input, char ifMatch, Pattern pattern, String replacement) {
|
||||||
if (input.indexOf(match) != -1) {
|
if (input.indexOf(ifMatch) != -1) {
|
||||||
input = CHAR_TO_PATTERN.get(match).matcher(input).replaceAll(replacement);
|
input = pattern.matcher(input).replaceAll(replacement);
|
||||||
}
|
}
|
||||||
return input;
|
return input;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
public static String replaceAll(String input, char match, String replacement) {
|
||||||
* converts an {@link OutputStream} to an {@link OutputSupplier}
|
if (input.indexOf(match) != -1) {
|
||||||
*
|
input = CHAR_TO_PATTERN.get(match).matcher(input).replaceAll(replacement);
|
||||||
*/
|
}
|
||||||
public static OutputSupplier<OutputStream> newOutputStreamSupplier(final OutputStream output) {
|
return input;
|
||||||
checkNotNull(output, "output");
|
}
|
||||||
return new OutputSupplier<OutputStream>() {
|
|
||||||
public OutputStream getOutput() throws IOException {
|
|
||||||
return output;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
public static boolean enventuallyTrue(Supplier<Boolean> assertion, long inconsistencyMillis)
|
/**
|
||||||
|
* converts an {@link OutputStream} to an {@link OutputSupplier}
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public static OutputSupplier<OutputStream> newOutputStreamSupplier(final OutputStream output) {
|
||||||
|
checkNotNull(output, "output");
|
||||||
|
return new OutputSupplier<OutputStream>() {
|
||||||
|
public OutputStream getOutput() throws IOException {
|
||||||
|
return output;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean enventuallyTrue(Supplier<Boolean> assertion, long inconsistencyMillis)
|
||||||
throws InterruptedException {
|
throws InterruptedException {
|
||||||
|
|
||||||
for (int i = 0; i < 30; i++) {
|
for (int i = 0; i < 30; i++) {
|
||||||
if (!assertion.get()) {
|
if (!assertion.get()) {
|
||||||
Thread.sleep(inconsistencyMillis / 30);
|
Thread.sleep(inconsistencyMillis / 30);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Resource
|
@Resource
|
||||||
protected static Logger logger = Logger.NULL;
|
protected static Logger logger = Logger.NULL;
|
||||||
|
|
||||||
public static String toStringAndClose(InputStream input) throws IOException {
|
public static String toStringAndClose(InputStream input) throws IOException {
|
||||||
checkNotNull(input, "input");
|
checkNotNull(input, "input");
|
||||||
try {
|
try {
|
||||||
return new String(ByteStreams.toByteArray(input), Charsets.UTF_8);
|
return new String(ByteStreams.toByteArray(input), Charsets.UTF_8);
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
logger.warn(e, "Failed to read from stream");
|
logger.warn(e, "Failed to read from stream");
|
||||||
return null;
|
return null;
|
||||||
} catch (NullPointerException e) {
|
} catch (NullPointerException e) {
|
||||||
return null;
|
return null;
|
||||||
} finally {
|
} finally {
|
||||||
Closeables.closeQuietly(input);
|
Closeables.closeQuietly(input);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static InputStream toInputStream(String in) {
|
public static InputStream toInputStream(String in) {
|
||||||
try {
|
try {
|
||||||
return ByteStreams.newInputStreamSupplier(in.getBytes(Charsets.UTF_8)).getInput();
|
return ByteStreams.newInputStreamSupplier(in.getBytes(Charsets.UTF_8)).getInput();
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
logger.warn(e, "Failed to convert %s to an inputStream", in);
|
logger.warn(e, "Failed to convert %s to an inputStream", in);
|
||||||
throw new RuntimeException(e);
|
throw new RuntimeException(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Encode the given string with the given encoding, if possible. If the encoding fails with
|
* Encode the given string with the given encoding, if possible. If the encoding fails with
|
||||||
* {@link UnsupportedEncodingException}, log a warning and fall back to the system's default
|
* {@link UnsupportedEncodingException}, log a warning and fall back to the system's default
|
||||||
* encoding.
|
* encoding.
|
||||||
*
|
*
|
||||||
* @param str
|
* @param str
|
||||||
* what to encode
|
* what to encode
|
||||||
* @param charsetName
|
* @param charsetName
|
||||||
* the name of a supported {@link java.nio.charset.Charset </code>charset<code>}
|
* the name of a supported {@link java.nio.charset.Charset </code>charset<code>}
|
||||||
* @return properly encoded String.
|
* @return properly encoded String.
|
||||||
*/
|
*/
|
||||||
public static byte[] encodeString(String str, String charsetName) {
|
public static byte[] encodeString(String str, String charsetName) {
|
||||||
try {
|
try {
|
||||||
return str.getBytes(charsetName);
|
return str.getBytes(charsetName);
|
||||||
} catch (UnsupportedEncodingException e) {
|
} catch (UnsupportedEncodingException e) {
|
||||||
logger.warn(e, "Failed to encode string to bytes with encoding " + charsetName
|
logger.warn(e, "Failed to encode string to bytes with encoding " + charsetName
|
||||||
+ ". Falling back to system's default encoding");
|
+ ". Falling back to system's default encoding");
|
||||||
return str.getBytes();
|
return str.getBytes();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Encode the given string with the UTF-8 encoding, the sane default. In the very unlikely event
|
* Encode the given string with the UTF-8 encoding, the sane default. In the very unlikely event
|
||||||
* the encoding fails with {@link UnsupportedEncodingException}, log a warning and fall back to
|
* the encoding fails with {@link UnsupportedEncodingException}, log a warning and fall back to
|
||||||
* the system's default encoding.
|
* the system's default encoding.
|
||||||
*
|
*
|
||||||
* @param str
|
* @param str
|
||||||
* what to encode
|
* what to encode
|
||||||
* @return properly encoded String.
|
* @return properly encoded String.
|
||||||
*/
|
*/
|
||||||
public static byte[] encodeString(String str) {
|
public static byte[] encodeString(String str) {
|
||||||
return encodeString(str, UTF8_ENCODING);
|
return encodeString(str, UTF8_ENCODING);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* replaces tokens that are expressed as <code>{token}</code>
|
* replaces tokens that are expressed as <code>{token}</code>
|
||||||
*
|
*
|
||||||
* <p/>
|
* <p/>
|
||||||
* ex. if input is "hello {where}"<br/>
|
* ex. if input is "hello {where}"<br/>
|
||||||
* and replacements is "where" -> "world" <br/>
|
* and replacements is "where" -> "world" <br/>
|
||||||
* then replaceTokens returns "hello world"
|
* then replaceTokens returns "hello world"
|
||||||
*
|
*
|
||||||
* @param input
|
* @param input
|
||||||
* source to replace
|
* source to replace
|
||||||
* @param replacements
|
* @param replacements
|
||||||
* token/value pairs
|
* token/value pairs
|
||||||
*/
|
*/
|
||||||
public static String replaceTokens(String input, Map<String, String> replacements) {
|
public static String replaceTokens(String input, Map<String, String> replacements) {
|
||||||
Matcher matcher = Patterns.TOKEN_PATTERN.matcher(input);
|
Matcher matcher = Patterns.TOKEN_PATTERN.matcher(input);
|
||||||
StringBuilder builder = new StringBuilder();
|
StringBuilder builder = new StringBuilder();
|
||||||
int i = 0;
|
int i = 0;
|
||||||
while (matcher.find()) {
|
while (matcher.find()) {
|
||||||
String replacement = replacements.get(matcher.group(1));
|
String replacement = replacements.get(matcher.group(1));
|
||||||
builder.append(input.substring(i, matcher.start()));
|
builder.append(input.substring(i, matcher.start()));
|
||||||
if (replacement == null)
|
if (replacement == null)
|
||||||
builder.append(matcher.group(0));
|
builder.append(matcher.group(0));
|
||||||
else
|
else
|
||||||
builder.append(replacement);
|
builder.append(replacement);
|
||||||
i = matcher.end();
|
i = matcher.end();
|
||||||
}
|
}
|
||||||
builder.append(input.substring(i, input.length()));
|
builder.append(input.substring(i, input.length()));
|
||||||
return builder.toString();
|
return builder.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Will throw an exception if the argument is null or empty.
|
* Will throw an exception if the argument is null or empty.
|
||||||
* @param nullableString
|
*
|
||||||
* string to verify. Can be null or empty.
|
* @param nullableString
|
||||||
*/
|
* string to verify. Can be null or empty.
|
||||||
public static void checkNotEmpty(String nullableString) {
|
*/
|
||||||
checkNotEmpty(nullableString, "Argument can't be null or empty");
|
public static void checkNotEmpty(String nullableString) {
|
||||||
}
|
checkNotEmpty(nullableString, "Argument can't be null or empty");
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Will throw an exception if the argument is null or empty. Accepts
|
* Will throw an exception if the argument is null or empty. Accepts a custom error message.
|
||||||
* a custom error message.
|
*
|
||||||
* @param nullableString
|
* @param nullableString
|
||||||
* string to verify. Can be null or empty.
|
* string to verify. Can be null or empty.
|
||||||
* @param message
|
* @param message
|
||||||
* message to show in case of exception
|
* message to show in case of exception
|
||||||
*/
|
*/
|
||||||
public static void checkNotEmpty(String nullableString, String message) {
|
public static void checkNotEmpty(String nullableString, String message) {
|
||||||
checkArgument(nullableString != null && nullableString.length() > 0,
|
checkArgument(nullableString != null && nullableString.length() > 0, message);
|
||||||
message);
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue