mirror of https://github.com/apache/jclouds.git
Merge pull request #1133 from jclouds/ec2-tagapi
moved off deprecated TagClient -> TagApi
This commit is contained in:
commit
1be4fbd993
|
@ -25,6 +25,7 @@ import static org.jclouds.aws.reference.AWSConstants.PROPERTY_HEADER_TAG;
|
|||
import static org.jclouds.compute.config.ComputeServiceProperties.RESOURCENAME_DELIMITER;
|
||||
import static org.jclouds.ec2.reference.EC2Constants.PROPERTY_EC2_AMI_OWNERS;
|
||||
import static org.jclouds.ec2.reference.EC2Constants.PROPERTY_EC2_AUTO_ALLOCATE_ELASTIC_IPS;
|
||||
import static org.jclouds.ec2.reference.EC2Constants.PROPERTY_EC2_GENERATE_INSTANCE_NAMES;
|
||||
import static org.jclouds.ec2.reference.EC2Constants.PROPERTY_EC2_TIMEOUT_SECURITYGROUP_PRESENT;
|
||||
|
||||
import java.net.URI;
|
||||
|
@ -88,6 +89,7 @@ public class EC2ApiMetadata extends BaseRestApiMetadata {
|
|||
properties.setProperty(PROPERTY_EC2_TIMEOUT_SECURITYGROUP_PRESENT, "500");
|
||||
properties.setProperty(PROPERTY_EC2_AUTO_ALLOCATE_ELASTIC_IPS, "false");
|
||||
properties.setProperty(RESOURCENAME_DELIMITER, "#");
|
||||
properties.setProperty(PROPERTY_EC2_GENERATE_INSTANCE_NAMES, "true");
|
||||
return properties;
|
||||
}
|
||||
|
||||
|
|
|
@ -24,11 +24,15 @@ import static org.jclouds.compute.config.ComputeServiceProperties.RESOURCENAME_D
|
|||
import static org.jclouds.compute.config.ComputeServiceProperties.TIMEOUT_NODE_RUNNING;
|
||||
import static org.jclouds.compute.config.ComputeServiceProperties.TIMEOUT_NODE_SUSPENDED;
|
||||
import static org.jclouds.compute.config.ComputeServiceProperties.TIMEOUT_NODE_TERMINATED;
|
||||
import static org.jclouds.compute.util.ComputeServiceUtils.addMetadataAndParseTagsFromValuesOfEmptyString;
|
||||
import static org.jclouds.compute.util.ComputeServiceUtils.metadataAndTagsAsValuesOfEmptyString;
|
||||
import static org.jclouds.ec2.reference.EC2Constants.PROPERTY_EC2_GENERATE_INSTANCE_NAMES;
|
||||
import static org.jclouds.ec2.util.Tags.resourceToTagsAsMap;
|
||||
import static org.jclouds.util.Preconditions2.checkNotEmpty;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.ConcurrentMap;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
|
@ -41,10 +45,13 @@ import org.jclouds.Constants;
|
|||
import org.jclouds.aws.util.AWSUtils;
|
||||
import org.jclouds.collect.Memoized;
|
||||
import org.jclouds.compute.ComputeServiceContext;
|
||||
import org.jclouds.compute.RunNodesException;
|
||||
import org.jclouds.compute.callables.RunScriptOnNode;
|
||||
import org.jclouds.compute.domain.Hardware;
|
||||
import org.jclouds.compute.domain.Image;
|
||||
import org.jclouds.compute.domain.NodeMetadata;
|
||||
import org.jclouds.compute.domain.NodeMetadataBuilder;
|
||||
import org.jclouds.compute.domain.Template;
|
||||
import org.jclouds.compute.domain.TemplateBuilder;
|
||||
import org.jclouds.compute.extensions.ImageExtension;
|
||||
import org.jclouds.compute.functions.GroupNamingConvention;
|
||||
|
@ -70,6 +77,8 @@ import org.jclouds.ec2.compute.domain.RegionNameAndIngressRules;
|
|||
import org.jclouds.ec2.compute.options.EC2TemplateOptions;
|
||||
import org.jclouds.ec2.domain.KeyPair;
|
||||
import org.jclouds.ec2.domain.RunningInstance;
|
||||
import org.jclouds.ec2.domain.Tag;
|
||||
import org.jclouds.ec2.util.TagFilterBuilder;
|
||||
import org.jclouds.predicates.Retryables;
|
||||
import org.jclouds.scriptbuilder.functions.InitAdminAccess;
|
||||
|
||||
|
@ -79,9 +88,13 @@ import com.google.common.base.Optional;
|
|||
import com.google.common.base.Predicate;
|
||||
import com.google.common.base.Supplier;
|
||||
import com.google.common.cache.LoadingCache;
|
||||
import com.google.common.collect.FluentIterable;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import com.google.common.collect.ImmutableMultimap;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import com.google.common.collect.ImmutableMultimap.Builder;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import com.google.common.collect.Maps;
|
||||
import com.google.common.collect.Multimap;
|
||||
import com.google.inject.Inject;
|
||||
|
||||
/**
|
||||
|
@ -89,10 +102,11 @@ import com.google.inject.Inject;
|
|||
*/
|
||||
@Singleton
|
||||
public class EC2ComputeService extends BaseComputeService {
|
||||
private final EC2Client ec2Client;
|
||||
private final EC2Client client;
|
||||
private final ConcurrentMap<RegionAndName, KeyPair> credentialsMap;
|
||||
private final LoadingCache<RegionAndName, String> securityGroupMap;
|
||||
private final Factory namingConvention;
|
||||
private final boolean generateInstanceNames;
|
||||
|
||||
@Inject
|
||||
protected EC2ComputeService(ComputeServiceContext context, Map<String, Credentials> credentialStore,
|
||||
|
@ -109,19 +123,74 @@ public class EC2ComputeService extends BaseComputeService {
|
|||
InitializeRunScriptOnNodeOrPlaceInBadMap.Factory initScriptRunnerFactory,
|
||||
RunScriptOnNode.Factory runScriptOnNodeFactory, InitAdminAccess initAdminAccess,
|
||||
PersistNodeCredentials persistNodeCredentials, Timeouts timeouts,
|
||||
@Named(Constants.PROPERTY_USER_THREADS) ExecutorService executor, EC2Client ec2Client,
|
||||
@Named(Constants.PROPERTY_USER_THREADS) ExecutorService executor, EC2Client client,
|
||||
ConcurrentMap<RegionAndName, KeyPair> credentialsMap,
|
||||
@Named("SECURITY") LoadingCache<RegionAndName, String> securityGroupMap,
|
||||
Optional<ImageExtension> imageExtension, GroupNamingConvention.Factory namingConvention) {
|
||||
Optional<ImageExtension> imageExtension, GroupNamingConvention.Factory namingConvention,
|
||||
@Named(PROPERTY_EC2_GENERATE_INSTANCE_NAMES) boolean generateInstanceNames) {
|
||||
super(context, credentialStore, images, sizes, locations, listNodesStrategy, getImageStrategy,
|
||||
getNodeMetadataStrategy, runNodesAndAddToSetStrategy, rebootNodeStrategy, destroyNodeStrategy,
|
||||
startNodeStrategy, stopNodeStrategy, templateBuilderProvider, templateOptionsProvider, nodeRunning,
|
||||
nodeTerminated, nodeSuspended, initScriptRunnerFactory, initAdminAccess, runScriptOnNodeFactory,
|
||||
persistNodeCredentials, timeouts, executor, imageExtension);
|
||||
this.ec2Client = ec2Client;
|
||||
this.client = client;
|
||||
this.credentialsMap = credentialsMap;
|
||||
this.securityGroupMap = securityGroupMap;
|
||||
this.namingConvention = namingConvention;
|
||||
this.generateInstanceNames = generateInstanceNames;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<? extends NodeMetadata> createNodesInGroup(String group, int count, final Template template)
|
||||
throws RunNodesException {
|
||||
Set<? extends NodeMetadata> nodes = super.createNodesInGroup(group, count, template);
|
||||
String region = AWSUtils.getRegionFromLocationOrNull(template.getLocation());
|
||||
if (client.getTagApiForRegion(region).isPresent()) {
|
||||
Map<String, String> common = metadataAndTagsAsValuesOfEmptyString(template.getOptions());
|
||||
if (common.size() > 0 || generateInstanceNames) {
|
||||
return addTagsToInstancesInRegion(common, nodes, region, group);
|
||||
}
|
||||
}
|
||||
return nodes;
|
||||
}
|
||||
|
||||
private static final Function<NodeMetadata, String> instanceId = new Function<NodeMetadata, String>() {
|
||||
@Override
|
||||
public String apply(NodeMetadata in) {
|
||||
return in.getProviderId();
|
||||
}
|
||||
};
|
||||
|
||||
private Set<NodeMetadata> addTagsToInstancesInRegion(Map<String, String> common, Set<? extends NodeMetadata> input,
|
||||
String region, String group) {
|
||||
Map<String, ? extends NodeMetadata> instancesById = Maps.uniqueIndex(input, instanceId);
|
||||
ImmutableSet.Builder<NodeMetadata> builder = ImmutableSet.<NodeMetadata> builder();
|
||||
if (generateInstanceNames && !common.containsKey("Name")) {
|
||||
for (String id : instancesById.keySet()) {
|
||||
Map<String, String> tags = ImmutableMap.<String, String> builder().putAll(common)
|
||||
.put("Name", id.replaceAll(".*-", group + "-")).build();
|
||||
logger.debug(">> applying tags %s to instance %s in region %s", tags, id, region);
|
||||
client.getTagApiForRegion(region).get().applyToResources(tags, ImmutableSet.of(id));
|
||||
builder.add(addTagsForInstance(tags, instancesById.get(id)));
|
||||
}
|
||||
} else {
|
||||
Iterable<String> ids = instancesById.keySet();
|
||||
logger.debug(">> applying tags %s to instances %s in region %s", common, ids, region);
|
||||
client.getTagApiForRegion(region).get().applyToResources(common, ids);
|
||||
for (NodeMetadata in : input)
|
||||
builder.add(addTagsForInstance(common, in));
|
||||
}
|
||||
if (logger.isDebugEnabled()) {
|
||||
Multimap<String, String> filter = new TagFilterBuilder().resourceIds(instancesById.keySet()).build();
|
||||
FluentIterable<Tag> tags = client.getTagApiForRegion(region).get().filter(filter);
|
||||
logger.debug("<< applied tags in region %s: %s", region, resourceToTagsAsMap(tags));
|
||||
}
|
||||
return builder.build();
|
||||
}
|
||||
|
||||
private static NodeMetadata addTagsForInstance(Map<String, String> tags, NodeMetadata input) {
|
||||
NodeMetadataBuilder builder = NodeMetadataBuilder.fromNodeMetadata(input).name(tags.get("Name"));
|
||||
return addMetadataAndParseTagsFromValuesOfEmptyString(builder, tags).build();
|
||||
}
|
||||
|
||||
@Inject(optional = true)
|
||||
|
@ -137,9 +206,9 @@ public class EC2ComputeService extends BaseComputeService {
|
|||
checkNotEmpty(group, "group");
|
||||
String groupName = namingConvention.create().sharedNameForGroup(group);
|
||||
|
||||
if (ec2Client.getSecurityGroupServices().describeSecurityGroupsInRegion(region, groupName).size() > 0) {
|
||||
if (client.getSecurityGroupServices().describeSecurityGroupsInRegion(region, groupName).size() > 0) {
|
||||
logger.debug(">> deleting securityGroup(%s)", groupName);
|
||||
ec2Client.getSecurityGroupServices().deleteSecurityGroupInRegion(region, groupName);
|
||||
client.getSecurityGroupServices().deleteSecurityGroupInRegion(region, groupName);
|
||||
// TODO: test this clear happens
|
||||
securityGroupMap.invalidate(new RegionNameAndIngressRules(region, groupName, null, false));
|
||||
logger.debug("<< deleted securityGroup(%s)", groupName);
|
||||
|
@ -148,20 +217,20 @@ public class EC2ComputeService extends BaseComputeService {
|
|||
|
||||
@VisibleForTesting
|
||||
void deleteKeyPair(String region, String group) {
|
||||
for (KeyPair keyPair : ec2Client.getKeyPairServices().describeKeyPairsInRegion(region)) {
|
||||
for (KeyPair keyPair : client.getKeyPairServices().describeKeyPairsInRegion(region)) {
|
||||
String keyName = keyPair.getKeyName();
|
||||
Predicate<String> keyNameMatcher = namingConvention.create().containsGroup(group);
|
||||
String oldKeyNameRegex = String.format("jclouds#%s#%s#%s", group, region, "[0-9a-f]+").replace('#', delimiter);
|
||||
// old keypair pattern too verbose as it has an unnecessary region qualifier
|
||||
|
||||
if (keyNameMatcher.apply(keyName) || keyName.matches(oldKeyNameRegex)) {
|
||||
Set<String> instancesUsingKeyPair = extractIdsFromInstances(filter(concat(ec2Client.getInstanceServices()
|
||||
Set<String> instancesUsingKeyPair = extractIdsFromInstances(filter(concat(client.getInstanceServices()
|
||||
.describeInstancesInRegion(region)), usingKeyPairAndNotDead(keyPair)));
|
||||
if (instancesUsingKeyPair.size() > 0) {
|
||||
logger.debug("<< inUse keyPair(%s), by (%s)", keyPair.getKeyName(), instancesUsingKeyPair);
|
||||
} else {
|
||||
logger.debug(">> deleting keyPair(%s)", keyPair.getKeyName());
|
||||
ec2Client.getKeyPairServices().deleteKeyPairInRegion(region, keyPair.getKeyName());
|
||||
client.getKeyPairServices().deleteKeyPairInRegion(region, keyPair.getKeyName());
|
||||
// TODO: test this clear happens
|
||||
credentialsMap.remove(new RegionAndName(region, keyPair.getKeyName()));
|
||||
credentialsMap.remove(new RegionAndName(region, group));
|
||||
|
@ -184,7 +253,6 @@ public class EC2ComputeService extends BaseComputeService {
|
|||
|
||||
protected Predicate<RunningInstance> usingKeyPairAndNotDead(final KeyPair keyPair) {
|
||||
return new Predicate<RunningInstance>() {
|
||||
|
||||
@Override
|
||||
public boolean apply(RunningInstance input) {
|
||||
switch (input.getInstanceState()) {
|
||||
|
@ -194,7 +262,6 @@ public class EC2ComputeService extends BaseComputeService {
|
|||
}
|
||||
return keyPair.getKeyName().equals(input.getKeyName());
|
||||
}
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -18,26 +18,33 @@
|
|||
*/
|
||||
package org.jclouds.ec2.compute.domain;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
|
||||
import com.google.common.base.Function;
|
||||
import com.google.common.base.Objects;
|
||||
import com.google.common.base.Objects.ToStringHelper;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Adrian Cole
|
||||
*/
|
||||
public class RegionAndName {
|
||||
|
||||
protected final String region;
|
||||
protected final String name;
|
||||
|
||||
public String slashEncode() {
|
||||
return new StringBuilder(region).append('/').append(name).toString();
|
||||
}
|
||||
|
||||
public RegionAndName(String region, String name) {
|
||||
this.region = region;
|
||||
this.name = name;
|
||||
this.region = checkNotNull(region, "region");
|
||||
this.name = checkNotNull(name, "name");
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
final int prime = 31;
|
||||
int result = 1;
|
||||
result = prime * result + ((region == null) ? 0 : region.hashCode());
|
||||
result = prime * result + ((name == null) ? 0 : name.hashCode());
|
||||
return result;
|
||||
return Objects.hashCode(region, name);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -46,20 +53,10 @@ public class RegionAndName {
|
|||
return true;
|
||||
if (obj == null)
|
||||
return false;
|
||||
if (getClass() != obj.getClass())
|
||||
if (!(obj instanceof RegionAndName))
|
||||
return false;
|
||||
RegionAndName other = (RegionAndName) obj;
|
||||
if (region == null) {
|
||||
if (other.region != null)
|
||||
return false;
|
||||
} else if (!region.equals(other.region))
|
||||
return false;
|
||||
if (name == null) {
|
||||
if (other.name != null)
|
||||
return false;
|
||||
} else if (!name.equals(other.name))
|
||||
return false;
|
||||
return true;
|
||||
RegionAndName other = RegionAndName.class.cast(obj);
|
||||
return Objects.equal(region, other.region) && Objects.equal(name, other.name);
|
||||
}
|
||||
|
||||
public String getRegion() {
|
||||
|
@ -72,7 +69,45 @@ public class RegionAndName {
|
|||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "[region=" + region + ", name=" + name + "]";
|
||||
return string().toString();
|
||||
}
|
||||
|
||||
protected ToStringHelper string() {
|
||||
return Objects.toStringHelper("").add("region", region).add("name", name);
|
||||
}
|
||||
|
||||
private static enum RegionFunction implements Function<RegionAndName, String> {
|
||||
INSTANCE;
|
||||
@Override
|
||||
public String apply(RegionAndName input) {
|
||||
return input.getRegion();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "getRegion()";
|
||||
}
|
||||
};
|
||||
|
||||
public static Function<RegionAndName, String> regionFunction() {
|
||||
return RegionFunction.INSTANCE;
|
||||
}
|
||||
|
||||
private static enum NameFunction implements Function<RegionAndName, String> {
|
||||
INSTANCE;
|
||||
@Override
|
||||
public String apply(RegionAndName input) {
|
||||
return input.getName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "getName()";
|
||||
}
|
||||
};
|
||||
|
||||
public static Function<RegionAndName, String> nameFunction() {
|
||||
return NameFunction.INSTANCE;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1,84 @@
|
|||
/**
|
||||
* Licensed to jclouds, Inc. (jclouds) under one or more
|
||||
* contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. jclouds 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.jclouds.ec2.compute.functions;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
import static com.google.common.collect.Iterables.concat;
|
||||
import static com.google.common.collect.Iterables.toArray;
|
||||
import static com.google.common.collect.Multimaps.index;
|
||||
import static com.google.common.collect.Multimaps.transformValues;
|
||||
import static org.jclouds.ec2.compute.domain.RegionAndName.nameFunction;
|
||||
import static org.jclouds.ec2.compute.domain.RegionAndName.regionFunction;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Set;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import javax.inject.Singleton;
|
||||
|
||||
import org.jclouds.ec2.EC2Client;
|
||||
import org.jclouds.ec2.compute.domain.RegionAndName;
|
||||
import org.jclouds.ec2.domain.RunningInstance;
|
||||
import org.jclouds.logging.Logger;
|
||||
|
||||
import com.google.common.base.Function;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import com.google.common.collect.ImmutableSet.Builder;
|
||||
import com.google.common.collect.Multimap;
|
||||
import com.google.inject.Inject;
|
||||
|
||||
/**
|
||||
* returns the instances present in the list. Makes a single rest call per aggregate on region.
|
||||
*
|
||||
* @author Adrian Cole
|
||||
*/
|
||||
@Singleton
|
||||
public class PresentInstances implements Function<Set<RegionAndName>, Set<RunningInstance>> {
|
||||
|
||||
@Resource
|
||||
protected Logger logger = Logger.NULL;
|
||||
|
||||
private final EC2Client client;
|
||||
|
||||
@Inject
|
||||
public PresentInstances(EC2Client client) {
|
||||
this.client = checkNotNull(client, "client");
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<RunningInstance> apply(Set<RegionAndName> regionAndIds) {
|
||||
if (checkNotNull(regionAndIds, "regionAndIds").isEmpty())
|
||||
return ImmutableSet.of();
|
||||
Builder<RunningInstance> builder = ImmutableSet.<RunningInstance> builder();
|
||||
Multimap<String, String> regionToInstanceIds = transformValues(index(regionAndIds, regionFunction()),
|
||||
nameFunction());
|
||||
for (String region : regionToInstanceIds.keySet()) {
|
||||
Collection<String> instanceIds = regionToInstanceIds.get(region);
|
||||
logger.trace("looking for instances %s in region %s", instanceIds, region);
|
||||
builder.addAll(concat(client.getInstanceServices().describeInstancesInRegion(region,
|
||||
toArray(instanceIds, String.class))));
|
||||
}
|
||||
return builder.build();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString(){
|
||||
return "presentInstances()";
|
||||
}
|
||||
}
|
|
@ -22,6 +22,7 @@ import static com.google.common.base.Preconditions.checkNotNull;
|
|||
import static com.google.common.base.Predicates.not;
|
||||
import static com.google.common.base.Strings.emptyToNull;
|
||||
import static com.google.common.collect.Iterables.filter;
|
||||
import static org.jclouds.compute.util.ComputeServiceUtils.addMetadataAndParseTagsFromValuesOfEmptyString;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
@ -101,11 +102,8 @@ public class RunningInstanceToNodeMetadata implements Function<RunningInstance,
|
|||
if (instance == null || instance.getId() == null)
|
||||
return null;
|
||||
NodeMetadataBuilder builder = new NodeMetadataBuilder();
|
||||
builder = buildInstance(instance, builder);
|
||||
return builder.build();
|
||||
}
|
||||
|
||||
protected NodeMetadataBuilder buildInstance(final RunningInstance instance, NodeMetadataBuilder builder) {
|
||||
builder.name(instance.getTags().get("Name"));
|
||||
addMetadataAndParseTagsFromValuesOfEmptyString(builder, instance.getTags());
|
||||
builder.providerId(instance.getId());
|
||||
builder.id(instance.getRegion() + "/" + instance.getId());
|
||||
String group = getGroupForInstance(instance);
|
||||
|
@ -145,7 +143,7 @@ public class RunningInstanceToNodeMetadata implements Function<RunningInstance,
|
|||
} catch (UncheckedExecutionException e) {
|
||||
logger.debug("error getting image for %s: %s", regionAndName, e);
|
||||
}
|
||||
return builder;
|
||||
return builder.build();
|
||||
}
|
||||
|
||||
protected void addCredentialsForInstance(NodeMetadataBuilder builder, RunningInstance instance) {
|
||||
|
|
|
@ -42,6 +42,7 @@ import com.google.common.base.Objects;
|
|||
import com.google.common.base.Objects.ToStringHelper;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import com.google.common.collect.Iterables;
|
||||
import com.google.common.hash.Hashing;
|
||||
import com.google.common.primitives.Bytes;
|
||||
|
||||
/**
|
||||
|
@ -119,7 +120,8 @@ public class EC2TemplateOptions extends TemplateOptions implements Cloneable {
|
|||
if (noKeyPair)
|
||||
toString.add("noKeyPair", noKeyPair);
|
||||
toString.add("keyPair", keyPair);
|
||||
toString.add("userData", userData);
|
||||
if (userData != null && userData.size() > 0)
|
||||
toString.add("userDataCksum", Hashing.crc32().hashBytes(Bytes.toArray(userData)));
|
||||
ImmutableSet<BlockDeviceMapping> mappings = blockDeviceMappings.build();
|
||||
if (mappings.size() != 0)
|
||||
toString.add("blockDeviceMappings", mappings);
|
||||
|
|
|
@ -1,70 +0,0 @@
|
|||
/**
|
||||
* Licensed to jclouds, Inc. (jclouds) under one or more
|
||||
* contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. jclouds 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.jclouds.ec2.compute.predicates;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
|
||||
import java.util.NoSuchElementException;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import javax.inject.Singleton;
|
||||
|
||||
import org.jclouds.ec2.EC2Client;
|
||||
import org.jclouds.ec2.compute.domain.RegionAndName;
|
||||
import org.jclouds.logging.Logger;
|
||||
import org.jclouds.rest.ResourceNotFoundException;
|
||||
|
||||
import com.google.common.base.Predicate;
|
||||
import com.google.common.collect.Iterables;
|
||||
import com.google.inject.Inject;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Adrian Cole
|
||||
*/
|
||||
@Singleton
|
||||
public class InstancePresent implements Predicate<RegionAndName> {
|
||||
|
||||
private final EC2Client client;
|
||||
|
||||
@Resource
|
||||
protected Logger logger = Logger.NULL;
|
||||
|
||||
@Inject
|
||||
public InstancePresent(EC2Client client) {
|
||||
this.client = checkNotNull(client, "client");
|
||||
}
|
||||
|
||||
public boolean apply(RegionAndName instance) {
|
||||
logger.trace("looking for instance %s/%s", instance.getRegion(), instance.getName());
|
||||
try {
|
||||
refresh(instance);
|
||||
return true;
|
||||
} catch (ResourceNotFoundException e) {
|
||||
return false;
|
||||
} catch (NoSuchElementException e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
protected void refresh(RegionAndName instance) {
|
||||
Iterables.getOnlyElement(Iterables.getOnlyElement(client.getInstanceServices().describeInstancesInRegion(
|
||||
instance.getRegion(), instance.getName())));
|
||||
}
|
||||
}
|
|
@ -17,9 +17,13 @@
|
|||
* under the License.
|
||||
*/
|
||||
package org.jclouds.ec2.compute.strategy;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
import static com.google.common.collect.Iterables.all;
|
||||
import static com.google.common.collect.Iterables.concat;
|
||||
import static com.google.common.collect.Iterables.size;
|
||||
import static com.google.common.collect.Iterables.transform;
|
||||
import static com.google.common.collect.Sets.difference;
|
||||
import static com.google.common.util.concurrent.Atomics.newReference;
|
||||
import static org.jclouds.compute.config.ComputeServiceProperties.TIMEOUT_NODE_RUNNING;
|
||||
import static org.jclouds.compute.functions.DefaultCredentialsFromImageOrOverridingCredentials.overrideDefaultCredentialsWithOptionsIfPresent;
|
||||
import static org.jclouds.ec2.compute.util.EC2ComputeUtils.getZoneFromLocationOrNull;
|
||||
|
@ -32,14 +36,12 @@ import java.util.concurrent.atomic.AtomicReference;
|
|||
import javax.annotation.Resource;
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Named;
|
||||
import javax.inject.Provider;
|
||||
import javax.inject.Singleton;
|
||||
|
||||
import org.jclouds.aws.util.AWSUtils;
|
||||
import org.jclouds.compute.config.CustomizationResponse;
|
||||
import org.jclouds.compute.domain.NodeMetadata;
|
||||
import org.jclouds.compute.domain.Template;
|
||||
import org.jclouds.compute.domain.TemplateBuilder;
|
||||
import org.jclouds.compute.options.TemplateOptions;
|
||||
import org.jclouds.compute.reference.ComputeServiceConstants;
|
||||
import org.jclouds.compute.strategy.CreateNodesInGroupThenAddToSet;
|
||||
|
@ -48,7 +50,7 @@ import org.jclouds.domain.Credentials;
|
|||
import org.jclouds.domain.LoginCredentials;
|
||||
import org.jclouds.ec2.EC2Client;
|
||||
import org.jclouds.ec2.compute.domain.RegionAndName;
|
||||
import org.jclouds.ec2.compute.predicates.InstancePresent;
|
||||
import org.jclouds.ec2.compute.functions.PresentInstances;
|
||||
import org.jclouds.ec2.domain.RunningInstance;
|
||||
import org.jclouds.ec2.options.RunInstancesOptions;
|
||||
import org.jclouds.ec2.reference.EC2Constants;
|
||||
|
@ -56,14 +58,12 @@ import org.jclouds.logging.Logger;
|
|||
|
||||
import com.google.common.annotations.VisibleForTesting;
|
||||
import com.google.common.base.Function;
|
||||
import com.google.common.base.Joiner;
|
||||
import com.google.common.base.Predicate;
|
||||
import com.google.common.cache.LoadingCache;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import com.google.common.collect.ImmutableSet.Builder;
|
||||
import com.google.common.collect.Iterables;
|
||||
import com.google.common.collect.Maps;
|
||||
import com.google.common.collect.Multimap;
|
||||
import com.google.common.util.concurrent.Atomics;
|
||||
|
||||
/**
|
||||
* creates futures that correlate to
|
||||
|
@ -94,27 +94,23 @@ public class EC2CreateNodesInGroupThenAddToSet implements CreateNodesInGroupThen
|
|||
final Function<RunningInstance, NodeMetadata> runningInstanceToNodeMetadata;
|
||||
@VisibleForTesting
|
||||
final ComputeUtils utils;
|
||||
final InstancePresent instancePresent;
|
||||
final PresentInstances presentInstances;
|
||||
final LoadingCache<RunningInstance, LoginCredentials> instanceToCredentials;
|
||||
final Map<String, Credentials> credentialStore;
|
||||
final Provider<TemplateBuilder> templateBuilderProvider;
|
||||
|
||||
@Inject
|
||||
protected EC2CreateNodesInGroupThenAddToSet(
|
||||
EC2Client client,
|
||||
@Named("ELASTICIP")
|
||||
LoadingCache<RegionAndName, String> elasticIpCache,
|
||||
@Named("ELASTICIP") LoadingCache<RegionAndName, String> elasticIpCache,
|
||||
@Named(TIMEOUT_NODE_RUNNING) Predicate<AtomicReference<NodeMetadata>> nodeRunning,
|
||||
Provider<TemplateBuilder> templateBuilderProvider,
|
||||
CreateKeyPairAndSecurityGroupsAsNeededAndReturnRunOptions createKeyPairAndSecurityGroupsAsNeededAndReturncustomize,
|
||||
InstancePresent instancePresent, Function<RunningInstance, NodeMetadata> runningInstanceToNodeMetadata,
|
||||
LoadingCache<RunningInstance, LoginCredentials> instanceToCredentials, Map<String, Credentials> credentialStore,
|
||||
ComputeUtils utils) {
|
||||
PresentInstances presentInstances, Function<RunningInstance, NodeMetadata> runningInstanceToNodeMetadata,
|
||||
LoadingCache<RunningInstance, LoginCredentials> instanceToCredentials,
|
||||
Map<String, Credentials> credentialStore, ComputeUtils utils) {
|
||||
this.client = checkNotNull(client, "client");
|
||||
this.elasticIpCache = checkNotNull(elasticIpCache, "elasticIpCache");
|
||||
this.nodeRunning = checkNotNull(nodeRunning, "nodeRunning");
|
||||
this.templateBuilderProvider = checkNotNull(templateBuilderProvider, "templateBuilderProvider");
|
||||
this.instancePresent = checkNotNull(instancePresent, "instancePresent");
|
||||
this.presentInstances = checkNotNull(presentInstances, "presentInstances");
|
||||
this.createKeyPairAndSecurityGroupsAsNeededAndReturncustomize = checkNotNull(
|
||||
createKeyPairAndSecurityGroupsAsNeededAndReturncustomize,
|
||||
"createKeyPairAndSecurityGroupsAsNeededAndReturncustomize");
|
||||
|
@ -137,83 +133,83 @@ public class EC2CreateNodesInGroupThenAddToSet implements CreateNodesInGroupThen
|
|||
|
||||
Template mutableTemplate = template.clone();
|
||||
|
||||
Iterable<String> ips = allocateElasticIpsInRegion(count, mutableTemplate);
|
||||
|
||||
Iterable<? extends RunningInstance> started = createKeyPairAndSecurityGroupsAsNeededThenRunInstances(group,
|
||||
count, mutableTemplate);
|
||||
|
||||
Iterable<RegionAndName> ids = transform(started, instanceToRegionAndName);
|
||||
|
||||
String idsString = Joiner.on(',').join(ids);
|
||||
if (Iterables.size(ids) > 0) {
|
||||
logger.debug("<< started instances(%s)", idsString);
|
||||
all(ids, instancePresent);
|
||||
logger.debug("<< present instances(%s)", idsString);
|
||||
Set<RunningInstance> started = runInstancesAndWarnOnInvisible(group, count, mutableTemplate);
|
||||
if (started.size() == 0) {
|
||||
logger.warn("<< unable to start instances(%s)", mutableTemplate);
|
||||
return ImmutableMap.of();
|
||||
}
|
||||
populateCredentials(started, template.getOptions());
|
||||
|
||||
if (autoAllocateElasticIps) // before customization as the elastic ips may be needed
|
||||
blockUntilRunningAndAssignElasticIpsToInstancesOrPutIntoBadMap(started, badNodes);
|
||||
|
||||
return utils.customizeNodesAndAddToGoodMapOrPutExceptionIntoBadMap(mutableTemplate.getOptions(),
|
||||
transform(started, runningInstanceToNodeMetadata), goodNodes, badNodes, customizationResponses);
|
||||
}
|
||||
|
||||
assignElasticIpsToInstances(ips, started);
|
||||
/**
|
||||
* attempts to start the specified count of instances. eventual consistency might cause a problem where instances
|
||||
* aren't immediately visible to the api. This method will warn when that occurs.
|
||||
*/
|
||||
private Set<RunningInstance> runInstancesAndWarnOnInvisible(String group, int count, Template mutableTemplate) {
|
||||
Set<RunningInstance> started = createKeyPairAndSecurityGroupsAsNeededThenRunInstances(group, count,
|
||||
mutableTemplate);
|
||||
Set<RegionAndName> startedIds = ImmutableSet.copyOf(transform(started, instanceToRegionAndName));
|
||||
if (startedIds.size() == 0) {
|
||||
return ImmutableSet.copyOf(started);
|
||||
}
|
||||
logger.debug("<< started instances(%s)", startedIds);
|
||||
Set<RunningInstance> visible = presentInstances.apply(startedIds);
|
||||
Set<RegionAndName> visibleIds = ImmutableSet.copyOf(transform(visible, instanceToRegionAndName));
|
||||
logger.trace("<< visible instances(%s)", visibleIds);
|
||||
|
||||
return utils.customizeNodesAndAddToGoodMapOrPutExceptionIntoBadMap(mutableTemplate.getOptions(), transform(started,
|
||||
runningInstanceToNodeMetadata), goodNodes, badNodes, customizationResponses);
|
||||
// add an exception for each of the nodes we cannot customize
|
||||
Set<RegionAndName> invisibleIds = difference(startedIds, visibleIds);
|
||||
if (invisibleIds.size() > 0) {
|
||||
logger.warn("<< not api visible instances(%s)", invisibleIds);
|
||||
}
|
||||
return started;
|
||||
}
|
||||
|
||||
protected void populateCredentials(Iterable<? extends RunningInstance> started, TemplateOptions options) {
|
||||
private void populateCredentials(Set<RunningInstance> input, TemplateOptions options) {
|
||||
LoginCredentials credentials = null;
|
||||
for (RunningInstance instance : started) {
|
||||
for (RunningInstance instance : input) {
|
||||
credentials = instanceToCredentials.apply(instance);
|
||||
if (credentials != null)
|
||||
break;
|
||||
}
|
||||
credentials = overrideDefaultCredentialsWithOptionsIfPresent(credentials, options);
|
||||
if (credentials != null)
|
||||
for (RunningInstance instance : started)
|
||||
credentialStore.put("node#" + instance.getRegion() + "/" + instance.getId(), credentials);
|
||||
for (RegionAndName instance : transform(input, instanceToRegionAndName))
|
||||
credentialStore.put("node#" + instance.slashEncode(), credentials);
|
||||
}
|
||||
|
||||
protected Iterable<String> allocateElasticIpsInRegion(int count, Template template) {
|
||||
|
||||
Builder<String> ips = ImmutableSet.builder();
|
||||
if (!autoAllocateElasticIps)
|
||||
return ips.build();
|
||||
|
||||
String region = AWSUtils.getRegionFromLocationOrNull(template.getLocation());
|
||||
logger.debug("<< allocating %d elastic IPs for nodes in region (%s)", count, region);
|
||||
|
||||
for (int i = 0; i < count; ++i) {
|
||||
ips.add(client.getElasticIPAddressServices().allocateAddressInRegion(region));
|
||||
}
|
||||
return ips.build();
|
||||
}
|
||||
|
||||
protected void assignElasticIpsToInstances(Iterable<String> ips, Iterable<? extends RunningInstance> startedInstances) {
|
||||
|
||||
if (!autoAllocateElasticIps)
|
||||
return;
|
||||
|
||||
// TODO parallel
|
||||
int i = 0;
|
||||
for (RunningInstance startedInstance : startedInstances) {
|
||||
String ip = Iterables.get(ips, i);
|
||||
String region = startedInstance.getRegion();
|
||||
String id = startedInstance.getId();
|
||||
RegionAndName coordinates = new RegionAndName(region, id);
|
||||
|
||||
private void blockUntilRunningAndAssignElasticIpsToInstancesOrPutIntoBadMap(Set<RunningInstance> input,
|
||||
Map<NodeMetadata, Exception> badNodes) {
|
||||
Map<RegionAndName, RunningInstance> instancesById = Maps.uniqueIndex(input, instanceToRegionAndName);
|
||||
for (RegionAndName id : instancesById.keySet()) {
|
||||
try {
|
||||
logger.debug("<< allocating elastic IP instance(%s)", id);
|
||||
String ip = client.getElasticIPAddressServices().allocateAddressInRegion(id.getRegion());
|
||||
// block until instance is running
|
||||
logger.debug(">> awaiting status running instance(%s)", coordinates);
|
||||
AtomicReference<NodeMetadata> node = Atomics.newReference(runningInstanceToNodeMetadata.apply(startedInstance));
|
||||
logger.debug(">> awaiting status running instance(%s)", id);
|
||||
AtomicReference<NodeMetadata> node = newReference(runningInstanceToNodeMetadata
|
||||
.apply(instancesById.get(id)));
|
||||
nodeRunning.apply(node);
|
||||
logger.trace("<< running instance(%s)", coordinates);
|
||||
logger.debug(">> associating elastic IP %s to instance %s", ip, coordinates);
|
||||
client.getElasticIPAddressServices().associateAddressInRegion(region, ip, id);
|
||||
logger.trace("<< associated elastic IP %s to instance %s", ip, coordinates);
|
||||
logger.trace("<< running instance(%s)", id);
|
||||
logger.debug(">> associating elastic IP %s to instance %s", ip, id);
|
||||
client.getElasticIPAddressServices().associateAddressInRegion(id.getRegion(), ip, id.getName());
|
||||
logger.trace("<< associated elastic IP %s to instance %s", ip, id);
|
||||
// add mapping of instance to ip into the cache
|
||||
elasticIpCache.put(coordinates, ip);
|
||||
elasticIpCache.put(id, ip);
|
||||
} catch (RuntimeException e) {
|
||||
badNodes.put(runningInstanceToNodeMetadata.apply(instancesById.get(id)), e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected Iterable<? extends RunningInstance> createKeyPairAndSecurityGroupsAsNeededThenRunInstances(String group,
|
||||
int count, Template template) {
|
||||
private Set<RunningInstance> createKeyPairAndSecurityGroupsAsNeededThenRunInstances(String group, int count,
|
||||
Template template) {
|
||||
String region = AWSUtils.getRegionFromLocationOrNull(template.getLocation());
|
||||
String zone = getZoneFromLocationOrNull(template.getLocation());
|
||||
RunInstancesOptions instanceOptions = createKeyPairAndSecurityGroupsAsNeededAndReturncustomize.execute(region,
|
||||
|
@ -221,21 +217,23 @@ public class EC2CreateNodesInGroupThenAddToSet implements CreateNodesInGroupThen
|
|||
return createNodesInRegionAndZone(region, zone, group, count, template, instanceOptions);
|
||||
}
|
||||
|
||||
protected Iterable<? extends RunningInstance> createNodesInRegionAndZone(String region, String zone, String group,
|
||||
int count, Template template, RunInstancesOptions instanceOptions) {
|
||||
protected Set<RunningInstance> createNodesInRegionAndZone(String region, String zone, String group, int count,
|
||||
Template template, RunInstancesOptions instanceOptions) {
|
||||
int countStarted = 0;
|
||||
int tries = 0;
|
||||
Iterable<? extends RunningInstance> started = ImmutableSet.<RunningInstance> of();
|
||||
Set<RunningInstance> started = ImmutableSet.<RunningInstance> of();
|
||||
|
||||
while (countStarted < count && tries++ < count) {
|
||||
if (logger.isDebugEnabled())
|
||||
logger.debug(">> running %d instance region(%s) zone(%s) ami(%s) params(%s)", count - countStarted, region,
|
||||
zone, template.getImage().getProviderId(), instanceOptions.buildFormParameters());
|
||||
|
||||
started = Iterables.concat(started, client.getInstanceServices().runInstancesInRegion(region, zone,
|
||||
template.getImage().getProviderId(), 1, count - countStarted, instanceOptions));
|
||||
started = ImmutableSet.copyOf(concat(
|
||||
started,
|
||||
client.getInstanceServices().runInstancesInRegion(region, zone, template.getImage().getProviderId(), 1,
|
||||
count - countStarted, instanceOptions)));
|
||||
|
||||
countStarted = Iterables.size(started);
|
||||
countStarted = size(started);
|
||||
if (countStarted < count)
|
||||
logger.debug(">> not enough instances (%d/%d) started, attempting again", countStarted, count);
|
||||
}
|
||||
|
|
|
@ -28,6 +28,7 @@ import org.jclouds.javax.annotation.Nullable;
|
|||
|
||||
import com.google.common.base.Objects;
|
||||
import com.google.common.base.Objects.ToStringHelper;
|
||||
import com.google.common.base.Strings;
|
||||
import com.google.common.collect.ComparisonChain;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
|
@ -42,11 +43,18 @@ import com.google.common.collect.Sets;
|
|||
* @author Adrian Cole
|
||||
*/
|
||||
public class RunningInstance implements Comparable<RunningInstance> {
|
||||
public static Builder builder() {
|
||||
return new Builder();
|
||||
|
||||
public static Builder<?> builder() {
|
||||
return new ConcreteBuilder();
|
||||
}
|
||||
|
||||
public static class Builder {
|
||||
public Builder<?> toBuilder() {
|
||||
return new ConcreteBuilder().fromRunningInstance(this);
|
||||
}
|
||||
|
||||
public abstract static class Builder<T extends Builder<T>> {
|
||||
protected abstract T self();
|
||||
|
||||
protected String region;
|
||||
protected Set<String> groupNames = Sets.newLinkedHashSet();
|
||||
protected String amiLaunchIndex;
|
||||
|
@ -70,157 +78,174 @@ public class RunningInstance implements Comparable<RunningInstance> {
|
|||
protected RootDeviceType rootDeviceType = RootDeviceType.INSTANCE_STORE;
|
||||
protected String rootDeviceName;
|
||||
protected Map<String, BlockDevice> ebsBlockDevices = Maps.newLinkedHashMap();
|
||||
protected Map<String, String> tags = Maps.newLinkedHashMap();
|
||||
|
||||
public Builder region(String region) {
|
||||
public T tags(Map<String, String> tags) {
|
||||
this.tags = ImmutableMap.copyOf(checkNotNull(tags, "tags"));
|
||||
return self();
|
||||
}
|
||||
|
||||
public T tag(String key, String value) {
|
||||
if (key != null)
|
||||
this.tags.put(key, Strings.nullToEmpty(value));
|
||||
return self();
|
||||
}
|
||||
|
||||
public T region(String region) {
|
||||
this.region = region;
|
||||
return this;
|
||||
return self();
|
||||
}
|
||||
|
||||
public Builder groupNames(Iterable<String> groupNames) {
|
||||
public T groupNames(Iterable<String> groupNames) {
|
||||
this.groupNames = ImmutableSet.copyOf(checkNotNull(groupNames, "groupNames"));
|
||||
return this;
|
||||
return self();
|
||||
}
|
||||
|
||||
public Builder groupName(String groupName) {
|
||||
public T groupName(String groupName) {
|
||||
if (groupName != null)
|
||||
this.groupNames.add(groupName);
|
||||
return this;
|
||||
return self();
|
||||
}
|
||||
|
||||
public Builder amiLaunchIndex(String amiLaunchIndex) {
|
||||
public T amiLaunchIndex(String amiLaunchIndex) {
|
||||
this.amiLaunchIndex = amiLaunchIndex;
|
||||
return this;
|
||||
return self();
|
||||
}
|
||||
|
||||
public Builder dnsName(String dnsName) {
|
||||
public T dnsName(String dnsName) {
|
||||
this.dnsName = dnsName;
|
||||
return this;
|
||||
return self();
|
||||
}
|
||||
|
||||
public Builder imageId(String imageId) {
|
||||
public T imageId(String imageId) {
|
||||
this.imageId = imageId;
|
||||
return this;
|
||||
return self();
|
||||
}
|
||||
|
||||
public Builder instanceId(String instanceId) {
|
||||
public T instanceId(String instanceId) {
|
||||
this.instanceId = instanceId;
|
||||
return this;
|
||||
return self();
|
||||
}
|
||||
|
||||
public Builder instanceState(InstanceState instanceState) {
|
||||
public T instanceState(InstanceState instanceState) {
|
||||
this.instanceState = instanceState;
|
||||
return this;
|
||||
return self();
|
||||
}
|
||||
|
||||
public Builder rawState(String rawState) {
|
||||
public T rawState(String rawState) {
|
||||
this.rawState = rawState;
|
||||
return this;
|
||||
return self();
|
||||
}
|
||||
|
||||
public Builder instanceType(String instanceType) {
|
||||
public T instanceType(String instanceType) {
|
||||
this.instanceType = instanceType;
|
||||
return this;
|
||||
return self();
|
||||
}
|
||||
|
||||
public Builder ipAddress(String ipAddress) {
|
||||
public T ipAddress(String ipAddress) {
|
||||
this.ipAddress = ipAddress;
|
||||
return this;
|
||||
return self();
|
||||
}
|
||||
|
||||
public Builder kernelId(String kernelId) {
|
||||
public T kernelId(String kernelId) {
|
||||
this.kernelId = kernelId;
|
||||
return this;
|
||||
return self();
|
||||
}
|
||||
|
||||
public Builder keyName(String keyName) {
|
||||
public T keyName(String keyName) {
|
||||
this.keyName = keyName;
|
||||
return this;
|
||||
return self();
|
||||
}
|
||||
|
||||
public Builder launchTime(Date launchTime) {
|
||||
public T launchTime(Date launchTime) {
|
||||
this.launchTime = launchTime;
|
||||
return this;
|
||||
return self();
|
||||
}
|
||||
|
||||
public Builder availabilityZone(String availabilityZone) {
|
||||
public T availabilityZone(String availabilityZone) {
|
||||
this.availabilityZone = availabilityZone;
|
||||
return this;
|
||||
return self();
|
||||
}
|
||||
|
||||
public Builder virtualizationType(String virtualizationType) {
|
||||
public T virtualizationType(String virtualizationType) {
|
||||
this.virtualizationType = virtualizationType;
|
||||
return this;
|
||||
return self();
|
||||
}
|
||||
|
||||
public Builder platform(String platform) {
|
||||
public T platform(String platform) {
|
||||
this.platform = platform;
|
||||
return this;
|
||||
return self();
|
||||
}
|
||||
|
||||
public Builder privateDnsName(String privateDnsName) {
|
||||
public T privateDnsName(String privateDnsName) {
|
||||
this.privateDnsName = privateDnsName;
|
||||
return this;
|
||||
return self();
|
||||
}
|
||||
|
||||
public Builder privateIpAddress(String privateIpAddress) {
|
||||
public T privateIpAddress(String privateIpAddress) {
|
||||
this.privateIpAddress = privateIpAddress;
|
||||
return this;
|
||||
return self();
|
||||
}
|
||||
|
||||
public Builder ramdiskId(String ramdiskId) {
|
||||
public T ramdiskId(String ramdiskId) {
|
||||
this.ramdiskId = ramdiskId;
|
||||
return this;
|
||||
return self();
|
||||
}
|
||||
|
||||
public Builder reason(String reason) {
|
||||
public T reason(String reason) {
|
||||
this.reason = reason;
|
||||
return this;
|
||||
return self();
|
||||
}
|
||||
|
||||
public Builder rootDeviceType(RootDeviceType rootDeviceType) {
|
||||
public T rootDeviceType(RootDeviceType rootDeviceType) {
|
||||
this.rootDeviceType = rootDeviceType;
|
||||
return this;
|
||||
return self();
|
||||
}
|
||||
|
||||
public Builder rootDeviceName(String rootDeviceName) {
|
||||
public T rootDeviceName(String rootDeviceName) {
|
||||
this.rootDeviceName = rootDeviceName;
|
||||
return this;
|
||||
return self();
|
||||
}
|
||||
|
||||
public Builder devices(Map<String, BlockDevice> ebsBlockDevices) {
|
||||
public T devices(Map<String, BlockDevice> ebsBlockDevices) {
|
||||
this.ebsBlockDevices = ImmutableMap.copyOf(checkNotNull(ebsBlockDevices, "ebsBlockDevices"));
|
||||
return this;
|
||||
return self();
|
||||
}
|
||||
|
||||
public Builder device(String key, BlockDevice value) {
|
||||
public T device(String key, BlockDevice value) {
|
||||
if (key != null && value != null)
|
||||
this.ebsBlockDevices.put(key, value);
|
||||
return self();
|
||||
}
|
||||
|
||||
public T fromRunningInstance(RunningInstance in) {
|
||||
return region(in.region).groupNames(in.groupNames).amiLaunchIndex(in.amiLaunchIndex).dnsName(in.dnsName)
|
||||
.imageId(in.imageId).instanceId(in.instanceId).instanceState(in.instanceState).rawState(in.rawState)
|
||||
.instanceType(in.instanceType).ipAddress(in.ipAddress).kernelId(in.kernelId).keyName(in.keyName)
|
||||
.launchTime(in.launchTime).availabilityZone(in.availabilityZone)
|
||||
.virtualizationType(in.virtualizationType).platform(in.platform).privateDnsName(in.privateDnsName)
|
||||
.privateIpAddress(in.privateIpAddress).ramdiskId(in.ramdiskId).reason(in.reason)
|
||||
.rootDeviceType(in.rootDeviceType).rootDeviceName(in.rootDeviceName).devices(in.ebsBlockDevices)
|
||||
.tags(in.tags);
|
||||
}
|
||||
|
||||
public abstract RunningInstance build();
|
||||
|
||||
}
|
||||
|
||||
private static class ConcreteBuilder extends Builder<ConcreteBuilder> {
|
||||
@Override
|
||||
protected ConcreteBuilder self() {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public RunningInstance build() {
|
||||
return new RunningInstance(region, groupNames, amiLaunchIndex, dnsName, imageId, instanceId, instanceState,
|
||||
rawState, instanceType, ipAddress, kernelId, keyName, launchTime, availabilityZone,
|
||||
virtualizationType, platform, privateDnsName, privateIpAddress, ramdiskId, reason, rootDeviceType,
|
||||
rootDeviceName, ebsBlockDevices);
|
||||
rawState, instanceType, ipAddress, kernelId, keyName, launchTime, availabilityZone, virtualizationType,
|
||||
platform, privateDnsName, privateIpAddress, ramdiskId, reason, rootDeviceType, rootDeviceName,
|
||||
ebsBlockDevices, tags);
|
||||
}
|
||||
|
||||
public String getDnsName() {
|
||||
return dnsName;
|
||||
}
|
||||
|
||||
public String getIpAddress() {
|
||||
return ipAddress;
|
||||
}
|
||||
|
||||
public String getPrivateDnsName() {
|
||||
return privateDnsName;
|
||||
}
|
||||
|
||||
public String getPrivateIpAddress() {
|
||||
return privateIpAddress;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
protected final String region;
|
||||
|
@ -256,6 +281,7 @@ public class RunningInstance implements Comparable<RunningInstance> {
|
|||
@Nullable
|
||||
protected final String rootDeviceName;
|
||||
protected final Map<String, BlockDevice> ebsBlockDevices;
|
||||
protected final Map<String, String> tags;
|
||||
|
||||
protected RunningInstance(String region, Iterable<String> groupNames, @Nullable String amiLaunchIndex,
|
||||
@Nullable String dnsName, String imageId, String instanceId, InstanceState instanceState, String rawState,
|
||||
|
@ -263,7 +289,7 @@ public class RunningInstance implements Comparable<RunningInstance> {
|
|||
Date launchTime, String availabilityZone, String virtualizationType, @Nullable String platform,
|
||||
@Nullable String privateDnsName, @Nullable String privateIpAddress, @Nullable String ramdiskId,
|
||||
@Nullable String reason, RootDeviceType rootDeviceType, @Nullable String rootDeviceName,
|
||||
Map<String, BlockDevice> ebsBlockDevices) {
|
||||
Map<String, BlockDevice> ebsBlockDevices, Map<String, String> tags) {
|
||||
this.region = checkNotNull(region, "region");
|
||||
this.amiLaunchIndex = amiLaunchIndex; // nullable on runinstances.
|
||||
this.dnsName = dnsName; // nullable on runinstances.
|
||||
|
@ -287,6 +313,7 @@ public class RunningInstance implements Comparable<RunningInstance> {
|
|||
this.rootDeviceName = rootDeviceName;
|
||||
this.ebsBlockDevices = ImmutableMap.copyOf(checkNotNull(ebsBlockDevices, "ebsBlockDevices for %s/%s", region, instanceId));
|
||||
this.groupNames = ImmutableSet.copyOf(checkNotNull(groupNames, "groupNames for %s/%s", region, instanceId));
|
||||
this.tags = ImmutableMap.<String, String> copyOf(checkNotNull(tags, "tags"));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -462,6 +489,13 @@ public class RunningInstance implements Comparable<RunningInstance> {
|
|||
return groupNames;
|
||||
}
|
||||
|
||||
/**
|
||||
* tags that are present in the instance
|
||||
*/
|
||||
public Map<String, String> getTags() {
|
||||
return tags;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int compareTo(RunningInstance other) {
|
||||
return ComparisonChain.start().compare(region, other.region).compare(instanceId, other.instanceId, Ordering.natural().nullsLast()).result();
|
||||
|
@ -489,7 +523,7 @@ public class RunningInstance implements Comparable<RunningInstance> {
|
|||
.add("ipAddress", ipAddress).add("dnsName", dnsName).add("privateIpAddress", privateIpAddress)
|
||||
.add("privateDnsName", privateDnsName).add("keyName", keyName).add("groupNames", groupNames)
|
||||
.add("platform", platform).add("launchTime", launchTime).add("rootDeviceName", rootDeviceName)
|
||||
.add("rootDeviceType", rootDeviceType).add("ebsBlockDevices", ebsBlockDevices);
|
||||
.add("rootDeviceType", rootDeviceType).add("ebsBlockDevices", ebsBlockDevices).add("tags", tags);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -18,6 +18,8 @@
|
|||
*/
|
||||
package org.jclouds.ec2.reference;
|
||||
|
||||
import org.jclouds.compute.ComputeService;
|
||||
|
||||
/**
|
||||
* Configuration properties and constants used in EC2 connections.
|
||||
*
|
||||
|
@ -40,4 +42,11 @@ public interface EC2Constants {
|
|||
* deallocate when the node is destroyed.
|
||||
*/
|
||||
public static final String PROPERTY_EC2_AUTO_ALLOCATE_ELASTIC_IPS = "jclouds.ec2.auto-allocate-elastic-ips";
|
||||
|
||||
/**
|
||||
* If this property is set to true(default), jclouds generate a name for each instance based on the group. ex.
|
||||
* i-ef34ae2 becomes hadoop-ef34ae2. Note that this depends on {@link EC2Api#getTagApi} returning present.
|
||||
*/
|
||||
public static final String PROPERTY_EC2_GENERATE_INSTANCE_NAMES = "jclouds.ec2.generate-instance-names";
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1,103 @@
|
|||
/**
|
||||
* Licensed to jclouds, Inc. (jclouds) under one or more
|
||||
* contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. jclouds 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.jclouds.ec2.util;
|
||||
|
||||
import static com.google.common.collect.Multimaps.index;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import org.jclouds.ec2.domain.Tag;
|
||||
|
||||
import com.google.common.base.Function;
|
||||
import com.google.common.collect.Maps;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Adrian Cole
|
||||
*/
|
||||
public class Tags {
|
||||
private Tags() {
|
||||
}
|
||||
|
||||
/**
|
||||
* maps the input on {@link Tag#getResourceId()} with a value of a map of its {@link Tag#getKey()} to
|
||||
* {@link Tag#getValue()}
|
||||
*/
|
||||
public static Map<String, Map<String, String>> resourceToTagsAsMap(Iterable<Tag> tags) {
|
||||
return Maps.transformValues(index(tags, resourceIdFunction()).asMap(),
|
||||
new Function<Iterable<Tag>, Map<String, String>>() {
|
||||
@Override
|
||||
public Map<String, String> apply(Iterable<Tag> in) {
|
||||
return Maps.transformValues(Maps.uniqueIndex(in, keyFunction()), valueFunction());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public static enum ValueFunction implements Function<Tag, String> {
|
||||
INSTANCE;
|
||||
@Override
|
||||
public String apply(Tag in) {
|
||||
return in.getValue().or("");
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "getValue()";
|
||||
}
|
||||
}
|
||||
|
||||
public static Function<Tag, String> valueFunction() {
|
||||
return ValueFunction.INSTANCE;
|
||||
}
|
||||
|
||||
public static enum KeyFunction implements Function<Tag, String> {
|
||||
INSTANCE;
|
||||
@Override
|
||||
public String apply(Tag in) {
|
||||
return in.getKey();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "getKey()";
|
||||
}
|
||||
}
|
||||
|
||||
public static Function<Tag, String> keyFunction() {
|
||||
return KeyFunction.INSTANCE;
|
||||
}
|
||||
|
||||
public static enum ResourceIdFunction implements Function<Tag, String> {
|
||||
INSTANCE;
|
||||
@Override
|
||||
public String apply(Tag in) {
|
||||
return in.getResourceId();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "getResourceId()";
|
||||
}
|
||||
}
|
||||
|
||||
public static Function<Tag, String> resourceIdFunction() {
|
||||
return ResourceIdFunction.INSTANCE;
|
||||
}
|
||||
|
||||
}
|
|
@ -42,7 +42,6 @@ import org.xml.sax.Attributes;
|
|||
|
||||
import com.google.common.base.Supplier;
|
||||
import com.google.common.collect.Sets;
|
||||
import com.google.inject.Provider;
|
||||
|
||||
/**
|
||||
*
|
||||
|
@ -52,21 +51,28 @@ public abstract class BaseReservationHandler<T> extends HandlerForGeneratedReque
|
|||
|
||||
protected final DateCodec dateCodec;
|
||||
protected final Supplier<String> defaultRegion;
|
||||
protected final Provider<Builder> builderProvider;
|
||||
|
||||
@Inject
|
||||
public BaseReservationHandler(DateCodecFactory dateCodecFactory, @Region Supplier<String> defaultRegion,
|
||||
Provider<RunningInstance.Builder> builderProvider) {
|
||||
public BaseReservationHandler(DateCodecFactory dateCodecFactory, @Region Supplier<String> defaultRegion) {
|
||||
this.dateCodec = dateCodecFactory.iso8601();
|
||||
this.defaultRegion = defaultRegion;
|
||||
this.builderProvider = builderProvider;
|
||||
this.builder = builderProvider.get();
|
||||
}
|
||||
|
||||
protected Builder<?> builder = newBuilder();
|
||||
|
||||
protected Builder<?> newBuilder() {
|
||||
return RunningInstance.builder();
|
||||
}
|
||||
|
||||
protected void inItem() {
|
||||
if (endOfInstanceItem()) {
|
||||
refineBuilderBeforeAddingInstance();
|
||||
instances.add(builder.build());
|
||||
builder = newBuilder();
|
||||
}
|
||||
}
|
||||
|
||||
protected StringBuilder currentText = new StringBuilder();
|
||||
|
||||
protected Builder builder;
|
||||
|
||||
protected int itemDepth;
|
||||
protected boolean inInstancesSet;
|
||||
protected boolean inProductCodes;
|
||||
|
@ -181,13 +187,6 @@ public abstract class BaseReservationHandler<T> extends HandlerForGeneratedReque
|
|||
currentText = new StringBuilder();
|
||||
}
|
||||
|
||||
protected void inItem() {
|
||||
if (endOfInstanceItem()) {
|
||||
refineBuilderBeforeAddingInstance();
|
||||
instances.add(builder.build());
|
||||
builder = builderProvider.get();
|
||||
}
|
||||
}
|
||||
|
||||
protected void refineBuilderBeforeAddingInstance() {
|
||||
String region = getRequest() != null ? AWSUtils.findRegionInArgsOrNull(getRequest()) : null;
|
||||
|
@ -195,10 +194,6 @@ public abstract class BaseReservationHandler<T> extends HandlerForGeneratedReque
|
|||
builder.groupNames(groupNames);
|
||||
}
|
||||
|
||||
protected Builder builder() {
|
||||
return builder;
|
||||
}
|
||||
|
||||
protected boolean endOfInstanceItem() {
|
||||
return itemDepth <= 2 && inInstancesSet && !inProductCodes && !inGroupSet;
|
||||
}
|
||||
|
|
|
@ -18,6 +18,8 @@
|
|||
*/
|
||||
package org.jclouds.ec2.xml;
|
||||
|
||||
import static org.jclouds.util.SaxUtils.equalsOrSuffix;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
@ -26,10 +28,11 @@ import org.jclouds.date.DateCodecFactory;
|
|||
import org.jclouds.ec2.domain.Reservation;
|
||||
import org.jclouds.ec2.domain.RunningInstance;
|
||||
import org.jclouds.location.Region;
|
||||
import org.xml.sax.Attributes;
|
||||
|
||||
import com.google.common.base.Supplier;
|
||||
import com.google.common.collect.Sets;
|
||||
import com.google.inject.Provider;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import com.google.common.collect.ImmutableSet.Builder;
|
||||
|
||||
/**
|
||||
* Parses the following XML document:
|
||||
|
@ -41,17 +44,52 @@ import com.google.inject.Provider;
|
|||
*/
|
||||
public class DescribeInstancesResponseHandler extends
|
||||
BaseReservationHandler<Set<Reservation<? extends RunningInstance>>> {
|
||||
private Set<Reservation<? extends RunningInstance>> reservations = Sets.newLinkedHashSet();
|
||||
private final TagSetHandler tagSetHandler;
|
||||
private Builder<Reservation<? extends RunningInstance>> reservations = ImmutableSet
|
||||
.<Reservation<? extends RunningInstance>> builder();
|
||||
private boolean inTagSet;
|
||||
|
||||
@Inject
|
||||
public DescribeInstancesResponseHandler(DateCodecFactory dateCodecFactory,
|
||||
@Region Supplier<String> defaultRegion, Provider<RunningInstance.Builder> builderProvider) {
|
||||
super(dateCodecFactory, defaultRegion, builderProvider);
|
||||
DescribeInstancesResponseHandler(DateCodecFactory dateCodecFactory, @Region Supplier<String> defaultRegion,
|
||||
TagSetHandler tagSetHandler) {
|
||||
super(dateCodecFactory, defaultRegion);
|
||||
this.tagSetHandler = tagSetHandler;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void startElement(String uri, String name, String qName, Attributes attrs) {
|
||||
super.startElement(uri, name, qName, attrs);
|
||||
if (equalsOrSuffix(qName, "tagSet")) {
|
||||
inTagSet = true;
|
||||
}
|
||||
if (inTagSet) {
|
||||
tagSetHandler.startElement(uri, name, qName, attrs);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void characters(char ch[], int start, int length) {
|
||||
if (inTagSet) {
|
||||
tagSetHandler.characters(ch, start, length);
|
||||
} else {
|
||||
super.characters(ch, start, length);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void endElement(String uri, String name, String qName) {
|
||||
if (equalsOrSuffix(qName, "tagSet")) {
|
||||
inTagSet = false;
|
||||
builder.tags(tagSetHandler.getResult());
|
||||
} else if (inTagSet) {
|
||||
tagSetHandler.endElement(uri, name, qName);
|
||||
}
|
||||
super.endElement(uri, name, qName);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<Reservation<? extends RunningInstance>> getResult() {
|
||||
return reservations;
|
||||
return reservations.build();
|
||||
}
|
||||
|
||||
protected boolean endOfReservationItem() {
|
||||
|
@ -67,4 +105,7 @@ public class DescribeInstancesResponseHandler extends
|
|||
}
|
||||
}
|
||||
|
||||
protected boolean endOfInstanceItem() {
|
||||
return itemDepth == 2 && inInstancesSet;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -26,7 +26,6 @@ import org.jclouds.ec2.domain.RunningInstance;
|
|||
import org.jclouds.location.Region;
|
||||
|
||||
import com.google.common.base.Supplier;
|
||||
import com.google.inject.Provider;
|
||||
|
||||
/**
|
||||
* Parses the following XML document:
|
||||
|
@ -39,9 +38,8 @@ import com.google.inject.Provider;
|
|||
public class RunInstancesResponseHandler extends BaseReservationHandler<Reservation<? extends RunningInstance>> {
|
||||
|
||||
@Inject
|
||||
public RunInstancesResponseHandler(DateCodecFactory dateCodecFactory, @Region Supplier<String> defaultRegion,
|
||||
Provider<RunningInstance.Builder> builderProvider) {
|
||||
super(dateCodecFactory, defaultRegion, builderProvider);
|
||||
public RunInstancesResponseHandler(DateCodecFactory dateCodecFactory, @Region Supplier<String> defaultRegion) {
|
||||
super(dateCodecFactory, defaultRegion);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -0,0 +1,80 @@
|
|||
/**
|
||||
* Licensed to jclouds, Inc. (jclouds) under one or more
|
||||
* contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. jclouds 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.jclouds.ec2.xml;
|
||||
|
||||
import static org.jclouds.util.SaxUtils.currentOrNull;
|
||||
import static org.jclouds.util.SaxUtils.equalsOrSuffix;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import org.jclouds.http.functions.ParseSax;
|
||||
import org.xml.sax.Attributes;
|
||||
|
||||
import com.google.common.base.Strings;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
|
||||
/**
|
||||
* @author grkvlt@apache.org
|
||||
*/
|
||||
public class TagSetHandler extends ParseSax.HandlerForGeneratedRequestWithResult<Map<String, String>> {
|
||||
private StringBuilder currentText = new StringBuilder();
|
||||
|
||||
private ImmutableMap.Builder<String, String> result;
|
||||
private boolean inItem = false;
|
||||
private String key;
|
||||
private String value;
|
||||
|
||||
public Map<String, String> getResult() {
|
||||
return result.build();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void startElement(String uri, String localName, String qName, Attributes attributes) {
|
||||
if (equalsOrSuffix(qName, "tagSet")) {
|
||||
result = ImmutableMap.builder();
|
||||
} else if (qName.equals("item")) {
|
||||
inItem = true;
|
||||
key = null;
|
||||
value = null;
|
||||
}
|
||||
currentText = new StringBuilder();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void endElement(String uri, String localName, String qName) {
|
||||
if (qName.equals("item")) {
|
||||
inItem = false;
|
||||
if (key != null) {
|
||||
result.put(key, Strings.nullToEmpty(value));
|
||||
}
|
||||
}
|
||||
if (inItem) {
|
||||
if (qName.equals("key")) {
|
||||
key = currentOrNull(currentText);
|
||||
} else if (qName.equals("value")) {
|
||||
value = currentOrNull(currentText);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void characters(char ch[], int start, int length) {
|
||||
currentText.append(ch, start, length);
|
||||
}
|
||||
}
|
|
@ -85,13 +85,14 @@ public class EC2ComputeServiceLiveTest extends BaseComputeServiceLiveTest {
|
|||
return new SshjSshClientModule();
|
||||
}
|
||||
|
||||
// normal ec2 does not support metadata
|
||||
@Override
|
||||
protected void checkUserMetadataContains(NodeMetadata node, ImmutableMap<String, String> userMetadata) {
|
||||
assert node.getUserMetadata().equals(ImmutableMap.<String, String> of()) : String.format(
|
||||
"node userMetadata did not match %s %s", userMetadata, node);
|
||||
if (view.unwrap(EC2ApiMetadata.CONTEXT_TOKEN).getApi().getTagApi().isPresent()) {
|
||||
super.checkUserMetadataContains(node, userMetadata);
|
||||
} else {
|
||||
assertTrue(node.getUserMetadata().isEmpty(), "not expecting metadata when tag extension isn't present" + node);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Test(enabled = true, dependsOnMethods = "testCorrectAuthException")
|
||||
public void testImagesResolveCorrectly() {
|
||||
|
@ -324,7 +325,7 @@ public class EC2ComputeServiceLiveTest extends BaseComputeServiceLiveTest {
|
|||
return instance;
|
||||
}
|
||||
|
||||
public static void cleanupExtendedStuffInRegion(String region, SecurityGroupClient securityGroupClient,
|
||||
protected static void cleanupExtendedStuffInRegion(String region, SecurityGroupClient securityGroupClient,
|
||||
KeyPairClient keyPairClient, String group) throws InterruptedException {
|
||||
try {
|
||||
for (SecurityGroup secgroup : securityGroupClient.describeSecurityGroupsInRegion(region))
|
||||
|
|
|
@ -0,0 +1,70 @@
|
|||
/**
|
||||
* Licensed to jclouds, Inc. (jclouds) under one or more
|
||||
* contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. jclouds 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.jclouds.ec2.compute.functions;
|
||||
|
||||
import static org.easymock.EasyMock.createMock;
|
||||
import static org.easymock.EasyMock.expect;
|
||||
import static org.easymock.EasyMock.replay;
|
||||
import static org.easymock.EasyMock.verify;
|
||||
import static org.testng.Assert.assertEquals;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
import org.jclouds.ec2.EC2Client;
|
||||
import org.jclouds.ec2.compute.domain.RegionAndName;
|
||||
import org.jclouds.ec2.domain.Reservation;
|
||||
import org.jclouds.ec2.domain.RunningInstance;
|
||||
import org.jclouds.ec2.services.InstanceClient;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
|
||||
/**
|
||||
* @author Adrian Cole
|
||||
*/
|
||||
@Test(groups = "unit")
|
||||
public class PresentInstancesTest {
|
||||
RunningInstance instance1 = createMock(RunningInstance.class);
|
||||
RunningInstance instance2 = createMock(RunningInstance.class);
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Test
|
||||
public void testWhenInstancesPresentSingleCall() {
|
||||
|
||||
EC2Client client = createMock(EC2Client.class);
|
||||
InstanceClient instanceClient = createMock(InstanceClient.class);
|
||||
|
||||
expect(client.getInstanceServices()).andReturn(instanceClient);
|
||||
|
||||
// avoid imatcher fail. if you change this, be sure to check multiple jres
|
||||
expect(instanceClient.describeInstancesInRegion("us-east-1", "i-aaaa", "i-bbbb")).andReturn(
|
||||
Set.class.cast(ImmutableSet.of(Reservation.builder().region("us-east-1")
|
||||
.instances(ImmutableSet.of(instance1, instance2)).build())));
|
||||
|
||||
replay(client, instanceClient);
|
||||
|
||||
PresentInstances fn = new PresentInstances(client);
|
||||
|
||||
assertEquals(fn.apply(ImmutableSet.of(new RegionAndName("us-east-1", "i-aaaa"), new RegionAndName("us-east-1",
|
||||
"i-bbbb"))), ImmutableSet.of(instance1, instance2));
|
||||
|
||||
verify(client, instanceClient);
|
||||
}
|
||||
|
||||
}
|
|
@ -36,7 +36,6 @@ import org.jclouds.compute.domain.NodeMetadata;
|
|||
import org.jclouds.compute.domain.NodeMetadata.Status;
|
||||
import org.jclouds.compute.domain.NodeMetadataBuilder;
|
||||
import org.jclouds.compute.domain.Template;
|
||||
import org.jclouds.compute.domain.TemplateBuilder;
|
||||
import org.jclouds.compute.predicates.AtomicNodeRunning;
|
||||
import org.jclouds.compute.strategy.GetNodeMetadataStrategy;
|
||||
import org.jclouds.compute.util.ComputeUtils;
|
||||
|
@ -47,9 +46,9 @@ import org.jclouds.domain.LocationScope;
|
|||
import org.jclouds.domain.LoginCredentials;
|
||||
import org.jclouds.ec2.EC2Client;
|
||||
import org.jclouds.ec2.compute.domain.RegionAndName;
|
||||
import org.jclouds.ec2.compute.functions.PresentInstances;
|
||||
import org.jclouds.ec2.compute.functions.RunningInstanceToNodeMetadata;
|
||||
import org.jclouds.ec2.compute.options.EC2TemplateOptions;
|
||||
import org.jclouds.ec2.compute.predicates.InstancePresent;
|
||||
import org.jclouds.ec2.domain.Reservation;
|
||||
import org.jclouds.ec2.domain.RunningInstance;
|
||||
import org.jclouds.ec2.options.RunInstancesOptions;
|
||||
|
@ -62,7 +61,6 @@ import com.google.common.cache.LoadingCache;
|
|||
import com.google.common.collect.ImmutableSet;
|
||||
import com.google.common.collect.Iterables;
|
||||
import com.google.common.collect.Multimap;
|
||||
import com.google.inject.util.Providers;
|
||||
|
||||
/**
|
||||
* @author Adrian Cole
|
||||
|
@ -81,8 +79,7 @@ public class EC2CreateNodesInGroupThenAddToSetTest {
|
|||
NodeMetadata nodeMetadata = new NodeMetadataBuilder().id(region + "/" + instanceCreatedId)
|
||||
.providerId(instanceCreatedId).status(Status.RUNNING).build();
|
||||
// setup mocks
|
||||
TemplateBuilder templateBuilder = createMock(TemplateBuilder.class);
|
||||
EC2CreateNodesInGroupThenAddToSet strategy = setupStrategy(templateBuilder, nodeMetadata);
|
||||
EC2CreateNodesInGroupThenAddToSet strategy = setupStrategy(nodeMetadata);
|
||||
InputParams input = new InputParams(location);
|
||||
InstanceClient instanceClient = createMock(InstanceClient.class);
|
||||
ElasticIPAddressClient ipClient = createMock(ElasticIPAddressClient.class);
|
||||
|
@ -122,7 +119,7 @@ public class EC2CreateNodesInGroupThenAddToSetTest {
|
|||
expect(instance.getRegion()).andReturn(region).atLeastOnce();
|
||||
expect(strategy.credentialStore.put("node#" + region + "/" + instanceCreatedId, creds)).andReturn(null);
|
||||
|
||||
expect(strategy.instancePresent.apply(new RegionAndName(region, instanceCreatedId))).andReturn(true);
|
||||
expect(strategy.presentInstances.apply(ImmutableSet.of(new RegionAndName(region, instanceCreatedId)))).andReturn(ImmutableSet.of(instance));
|
||||
expect(input.template.getOptions()).andReturn(input.options).atLeastOnce();
|
||||
expect(input.options.getLoginUser()).andReturn(null);
|
||||
expect(input.options.getLoginPassword()).andReturn(null);
|
||||
|
@ -135,7 +132,6 @@ public class EC2CreateNodesInGroupThenAddToSetTest {
|
|||
.andReturn(null);
|
||||
|
||||
// replay mocks
|
||||
replay(templateBuilder);
|
||||
replay(instanceClient);
|
||||
replay(ipClient);
|
||||
replay(ec2Options);
|
||||
|
@ -147,7 +143,6 @@ public class EC2CreateNodesInGroupThenAddToSetTest {
|
|||
strategy.execute(input.tag, input.count, input.template, input.nodes, input.badNodes, input.customization);
|
||||
|
||||
// verify mocks
|
||||
verify(templateBuilder);
|
||||
verify(instanceClient);
|
||||
verify(ipClient);
|
||||
verify(ec2Options);
|
||||
|
@ -195,8 +190,7 @@ public class EC2CreateNodesInGroupThenAddToSetTest {
|
|||
.providerId(instanceCreatedId).status(Status.RUNNING).build();
|
||||
|
||||
// setup mocks
|
||||
TemplateBuilder templateBuilder = createMock(TemplateBuilder.class);
|
||||
EC2CreateNodesInGroupThenAddToSet strategy = setupStrategy(templateBuilder, nodeMetadata);
|
||||
EC2CreateNodesInGroupThenAddToSet strategy = setupStrategy(nodeMetadata);
|
||||
InputParams input = new InputParams(location);
|
||||
InstanceClient instanceClient = createMock(InstanceClient.class);
|
||||
RunInstancesOptions ec2Options = createMock(RunInstancesOptions.class);
|
||||
|
@ -223,7 +217,7 @@ public class EC2CreateNodesInGroupThenAddToSetTest {
|
|||
expect(instance.getRegion()).andReturn(region).atLeastOnce();
|
||||
expect(strategy.credentialStore.put("node#" + region + "/" + instanceCreatedId, creds)).andReturn(null);
|
||||
|
||||
expect(strategy.instancePresent.apply(new RegionAndName(region, instanceCreatedId))).andReturn(true);
|
||||
expect(strategy.presentInstances.apply(ImmutableSet.of(new RegionAndName(region, instanceCreatedId)))).andReturn(ImmutableSet.of(instance));
|
||||
expect(input.template.getOptions()).andReturn(input.options).atLeastOnce();
|
||||
expect(input.options.getLoginUser()).andReturn(null);
|
||||
expect(input.options.getLoginPassword()).andReturn(null);
|
||||
|
@ -238,7 +232,6 @@ public class EC2CreateNodesInGroupThenAddToSetTest {
|
|||
.andReturn(null);
|
||||
|
||||
// replay mocks
|
||||
replay(templateBuilder);
|
||||
replay(instanceClient);
|
||||
replay(ec2Options);
|
||||
replay(instance);
|
||||
|
@ -249,7 +242,6 @@ public class EC2CreateNodesInGroupThenAddToSetTest {
|
|||
strategy.execute(input.tag, input.count, input.template, input.nodes, input.badNodes, input.customization);
|
||||
|
||||
// verify mocks
|
||||
verify(templateBuilder);
|
||||
verify(instanceClient);
|
||||
verify(ec2Options);
|
||||
verify(instance);
|
||||
|
@ -307,7 +299,7 @@ public class EC2CreateNodesInGroupThenAddToSetTest {
|
|||
verify(strategy.createKeyPairAndSecurityGroupsAsNeededAndReturncustomize);
|
||||
verify(strategy.client);
|
||||
verify(strategy.elasticIpCache);
|
||||
verify(strategy.instancePresent);
|
||||
verify(strategy.presentInstances);
|
||||
verify(strategy.runningInstanceToNodeMetadata);
|
||||
verify(strategy.instanceToCredentials);
|
||||
verify(strategy.credentialStore);
|
||||
|
@ -315,10 +307,10 @@ public class EC2CreateNodesInGroupThenAddToSetTest {
|
|||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private EC2CreateNodesInGroupThenAddToSet setupStrategy(TemplateBuilder template, final NodeMetadata node) {
|
||||
private EC2CreateNodesInGroupThenAddToSet setupStrategy(final NodeMetadata node) {
|
||||
EC2Client client = createMock(EC2Client.class);
|
||||
CreateKeyPairAndSecurityGroupsAsNeededAndReturnRunOptions createKeyPairAndSecurityGroupsAsNeededAndReturncustomize = createMock(CreateKeyPairAndSecurityGroupsAsNeededAndReturnRunOptions.class);
|
||||
InstancePresent instancePresent = createMock(InstancePresent.class);
|
||||
PresentInstances presentInstances = createMock(PresentInstances.class);
|
||||
RunningInstanceToNodeMetadata runningInstanceToNodeMetadata = createMock(RunningInstanceToNodeMetadata.class);
|
||||
LoadingCache<RunningInstance, LoginCredentials> instanceToCredentials = createMock(LoadingCache.class);
|
||||
LoadingCache<RegionAndName, String> elasticIpCache = createMock(LoadingCache.class);
|
||||
|
@ -334,15 +326,15 @@ public class EC2CreateNodesInGroupThenAddToSetTest {
|
|||
Map<String, Credentials> credentialStore = createMock(Map.class);
|
||||
ComputeUtils utils = createMock(ComputeUtils.class);
|
||||
return new EC2CreateNodesInGroupThenAddToSet(client, elasticIpCache, new AtomicNodeRunning(nodeRunning),
|
||||
Providers.<TemplateBuilder> of(template), createKeyPairAndSecurityGroupsAsNeededAndReturncustomize,
|
||||
instancePresent, runningInstanceToNodeMetadata, instanceToCredentials, credentialStore, utils);
|
||||
createKeyPairAndSecurityGroupsAsNeededAndReturncustomize, presentInstances, runningInstanceToNodeMetadata,
|
||||
instanceToCredentials, credentialStore, utils);
|
||||
}
|
||||
|
||||
private void replayStrategy(EC2CreateNodesInGroupThenAddToSet strategy) {
|
||||
replay(strategy.createKeyPairAndSecurityGroupsAsNeededAndReturncustomize);
|
||||
replay(strategy.client);
|
||||
replay(strategy.elasticIpCache);
|
||||
replay(strategy.instancePresent);
|
||||
replay(strategy.presentInstances);
|
||||
replay(strategy.runningInstanceToNodeMetadata);
|
||||
replay(strategy.instanceToCredentials);
|
||||
replay(strategy.credentialStore);
|
||||
|
|
|
@ -0,0 +1,57 @@
|
|||
/**
|
||||
* Licensed to jclouds, Inc. (jclouds) under one or more
|
||||
* contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. jclouds 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.jclouds.ec2.util;
|
||||
|
||||
import static org.jclouds.ec2.domain.Tag.ResourceType.IMAGE;
|
||||
import static org.jclouds.ec2.domain.Tag.ResourceType.INSTANCE;
|
||||
import static org.testng.Assert.assertEquals;
|
||||
|
||||
import org.jclouds.ec2.domain.Tag;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
|
||||
/**
|
||||
* @author Adrian Cole
|
||||
*/
|
||||
@Test
|
||||
public class TagsTest {
|
||||
Tag resourceTag1 = Tag.builder().resourceType(IMAGE).resourceId("1").key("key").value("value").build();
|
||||
|
||||
public void testValueFunction() {
|
||||
assertEquals(Tags.valueFunction().apply(resourceTag1), "value");
|
||||
}
|
||||
|
||||
public void testKeyFunction() {
|
||||
assertEquals(Tags.keyFunction().apply(resourceTag1), "key");
|
||||
}
|
||||
|
||||
Tag resourceTag2 = Tag.builder().resourceType(IMAGE).resourceId("1").key("foo").value("bar").build();
|
||||
Tag resource2Tag1 = Tag.builder().resourceType(INSTANCE).resourceId("2").key("absent").build();
|
||||
Tag resource2Tag2 = Tag.builder().resourceType(INSTANCE).resourceId("2").key("hello").value("world").build();
|
||||
|
||||
public void testResourceToTagsAsMap() {
|
||||
assertEquals(
|
||||
Tags.resourceToTagsAsMap(ImmutableSet.of(resourceTag1, resourceTag2, resource2Tag1, resource2Tag2)),
|
||||
ImmutableMap.of("1", ImmutableMap.of("key", "value", "foo", "bar"),
|
||||
"2", ImmutableMap.of("absent", "", "hello", "world")));
|
||||
}
|
||||
|
||||
}
|
|
@ -41,6 +41,7 @@ import org.testng.annotations.Test;
|
|||
|
||||
import com.google.common.base.Supplier;
|
||||
import com.google.common.base.Suppliers;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import com.google.inject.AbstractModule;
|
||||
import com.google.inject.Guice;
|
||||
|
@ -69,7 +70,7 @@ public class DescribeInstancesResponseHandlerTest extends BaseEC2HandlerTest {
|
|||
public void testWhenRunning() throws UnknownHostException {
|
||||
|
||||
Set<Reservation<RunningInstance>> contents = ImmutableSet.of(new Reservation<RunningInstance>(defaultRegion,
|
||||
ImmutableSet.of("adriancole.ec2ingress"), ImmutableSet.of(new RunningInstance.Builder().region(
|
||||
ImmutableSet.of("adriancole.ec2ingress"), ImmutableSet.of(RunningInstance.builder().region(
|
||||
defaultRegion).groupName("adriancole.ec2ingress").amiLaunchIndex("0").dnsName(
|
||||
"ec2-174-129-81-68.compute-1.amazonaws.com").imageId("ami-82e4b5c7").instanceId("i-0799056f")
|
||||
.instanceState(InstanceState.RUNNING).rawState("running").instanceType(InstanceType.M1_SMALL)
|
||||
|
@ -91,7 +92,7 @@ public class DescribeInstancesResponseHandlerTest extends BaseEC2HandlerTest {
|
|||
|
||||
public void testApplyInputStream() {
|
||||
Set<Reservation<RunningInstance>> contents = ImmutableSet.of(new Reservation<RunningInstance>(defaultRegion,
|
||||
ImmutableSet.of("default"), ImmutableSet.of(new RunningInstance.Builder().region(defaultRegion).groupName(
|
||||
ImmutableSet.of("default"), ImmutableSet.of(RunningInstance.builder().region(defaultRegion).groupName(
|
||||
"default").amiLaunchIndex("23").dnsName("ec2-72-44-33-4.compute-1.amazonaws.com").imageId(
|
||||
"ami-6ea54007").instanceId("i-28a64341").instanceState(InstanceState.RUNNING).rawState(
|
||||
"running").instanceType(InstanceType.M1_LARGE).kernelId("aki-ba3adfd3").keyName(
|
||||
|
@ -100,8 +101,9 @@ public class DescribeInstancesResponseHandlerTest extends BaseEC2HandlerTest {
|
|||
.availabilityZone("us-east-1b").virtualizationType("paravirtual").privateDnsName(
|
||||
"10-251-50-132.ec2.internal")// product codes
|
||||
// ImmutableSet.of("774F4FF8")
|
||||
.tags(ImmutableMap.of("Name","ec2-o", "Empty",""))
|
||||
.ramdiskId("ari-badbad00").rootDeviceType(RootDeviceType.INSTANCE_STORE).build(),
|
||||
new RunningInstance.Builder().region(defaultRegion).groupName("default").amiLaunchIndex("23")
|
||||
RunningInstance.builder().region(defaultRegion).groupName("default").amiLaunchIndex("23")
|
||||
.dnsName("ec2-72-44-33-6.compute-1.amazonaws.com").imageId("ami-6ea54007").instanceId(
|
||||
"i-28a64435").instanceState(InstanceState.RUNNING).rawState("running")
|
||||
.instanceType(InstanceType.M1_LARGE).kernelId("aki-ba3adfd3").keyName(
|
||||
|
@ -125,7 +127,7 @@ public class DescribeInstancesResponseHandlerTest extends BaseEC2HandlerTest {
|
|||
public void testEBS() throws UnknownHostException {
|
||||
|
||||
Set<Reservation<RunningInstance>> contents = ImmutableSet.of(new Reservation<RunningInstance>(defaultRegion,
|
||||
ImmutableSet.of("adriancole.ec2ebsingress"), ImmutableSet.of(new RunningInstance.Builder().region(
|
||||
ImmutableSet.of("adriancole.ec2ebsingress"), ImmutableSet.of(RunningInstance.builder().region(
|
||||
defaultRegion).groupName("adriancole.ec2ebsingress").amiLaunchIndex("0").dnsName(
|
||||
"ec2-75-101-203-146.compute-1.amazonaws.com").imageId("ami-849875ed").instanceId("i-e564438d")
|
||||
.instanceState(InstanceState.RUNNING).rawState("running").instanceType(InstanceType.M1_SMALL)
|
||||
|
|
|
@ -65,19 +65,19 @@ public class RunInstancesResponseHandlerTest extends BaseEC2HandlerTest {
|
|||
Reservation<? extends RunningInstance> expected = new Reservation<RunningInstance>(defaultRegion, ImmutableSet
|
||||
.of("default"), ImmutableSet.of(
|
||||
|
||||
new RunningInstance.Builder().region(defaultRegion).groupName("default").amiLaunchIndex("0")
|
||||
RunningInstance.builder().region(defaultRegion).groupName("default").amiLaunchIndex("0")
|
||||
.imageId("ami-60a54009").instanceId("i-2ba64342").instanceState(InstanceState.PENDING).rawState(
|
||||
"pending").instanceType(InstanceType.M1_SMALL).keyName("example-key-name").launchTime(
|
||||
dateService.iso8601DateParse("2007-08-07T11:51:50.000Z"))// MonitoringState.ENABLED,
|
||||
.availabilityZone("us-east-1b").build(),
|
||||
|
||||
new RunningInstance.Builder().region(defaultRegion).groupName("default").amiLaunchIndex("1")
|
||||
RunningInstance.builder().region(defaultRegion).groupName("default").amiLaunchIndex("1")
|
||||
.imageId("ami-60a54009").instanceId("i-2bc64242").instanceState(InstanceState.PENDING).rawState(
|
||||
"pending").instanceType(InstanceType.M1_SMALL).keyName("example-key-name").launchTime(
|
||||
dateService.iso8601DateParse("2007-08-07T11:51:50.000Z"))// MonitoringState.ENABLED,
|
||||
.availabilityZone("us-east-1b").build(),
|
||||
|
||||
new RunningInstance.Builder().region(defaultRegion).groupName("default").amiLaunchIndex("2")
|
||||
RunningInstance.builder().region(defaultRegion).groupName("default").amiLaunchIndex("2")
|
||||
.imageId("ami-60a54009").instanceId("i-2be64332").instanceState(InstanceState.PENDING).rawState(
|
||||
"pending").instanceType(InstanceType.M1_SMALL).keyName("example-key-name").launchTime(
|
||||
dateService.iso8601DateParse("2007-08-07T11:51:50.000Z"))// MonitoringState.ENABLED,
|
||||
|
@ -98,7 +98,7 @@ public class RunInstancesResponseHandlerTest extends BaseEC2HandlerTest {
|
|||
Reservation<? extends RunningInstance> expected = new Reservation<RunningInstance>(defaultRegion, ImmutableSet
|
||||
.of("jclouds#greenqloud-computeblock"), ImmutableSet.of(
|
||||
|
||||
new RunningInstance.Builder().region(defaultRegion).groupName("jclouds#greenqloud-computeblock").amiLaunchIndex("0")
|
||||
RunningInstance.builder().region(defaultRegion).groupName("jclouds#greenqloud-computeblock").amiLaunchIndex("0")
|
||||
.imageId("qmi-9ac92558").instanceId("i-01b0dac3").instanceState(InstanceState.PENDING).rawState(
|
||||
"pending").instanceType(InstanceType.M1_SMALL).keyName("jclouds#greenqloud-computeblock#35")
|
||||
.launchTime(dateService.iso8601DateParse("2012-06-15T19:06:35.000+00:00"))
|
||||
|
|
|
@ -38,6 +38,16 @@
|
|||
<kernelId>aki-ba3adfd3</kernelId>
|
||||
<ramdiskId>ari-badbad00</ramdiskId>
|
||||
<hypervisor>xen</hypervisor>
|
||||
<tagSet>
|
||||
<item>
|
||||
<key>Name</key>
|
||||
<value>ec2-o</value>
|
||||
</item>
|
||||
<item>
|
||||
<key>Empty</key>
|
||||
<value />
|
||||
</item>
|
||||
</tagSet>
|
||||
</item>
|
||||
<item>
|
||||
<instanceId>i-28a64435</instanceId>
|
||||
|
|
|
@ -21,7 +21,6 @@ package org.jclouds.aws.ec2;
|
|||
import static java.util.concurrent.TimeUnit.MINUTES;
|
||||
import static java.util.concurrent.TimeUnit.SECONDS;
|
||||
import static org.jclouds.Constants.PROPERTY_TIMEOUTS_PREFIX;
|
||||
import static org.jclouds.aws.ec2.reference.AWSEC2Constants.PROPERTY_EC2_GENERATE_INSTANCE_NAMES;
|
||||
import static org.jclouds.ec2.reference.EC2Constants.PROPERTY_EC2_AMI_OWNERS;
|
||||
|
||||
import java.util.Properties;
|
||||
|
@ -66,13 +65,11 @@ public class AWSEC2ApiMetadata extends EC2ApiMetadata {
|
|||
Properties properties = EC2ApiMetadata.defaultProperties();
|
||||
properties.setProperty(PROPERTY_TIMEOUTS_PREFIX + "default", SECONDS.toMillis(90) + "");
|
||||
properties.setProperty(PROPERTY_TIMEOUTS_PREFIX + "SpotInstanceClient.describeSpotPriceHistoryInRegion", MINUTES.toMillis(2) + "");
|
||||
|
||||
properties.remove(PROPERTY_EC2_AMI_OWNERS);
|
||||
// auth fail sometimes happens in EC2, as the rc.local script that injects the
|
||||
// authorized key executes after ssh has started.
|
||||
properties.setProperty("jclouds.ssh.max-retries", "7");
|
||||
properties.setProperty("jclouds.ssh.retry-auth", "true");
|
||||
properties.setProperty(PROPERTY_EC2_GENERATE_INSTANCE_NAMES, "true");
|
||||
return properties;
|
||||
}
|
||||
|
||||
|
|
|
@ -25,7 +25,6 @@ import org.jclouds.aws.ec2.services.AWSSecurityGroupAsyncClient;
|
|||
import org.jclouds.aws.ec2.services.MonitoringAsyncClient;
|
||||
import org.jclouds.aws.ec2.services.PlacementGroupAsyncClient;
|
||||
import org.jclouds.aws.ec2.services.SpotInstanceAsyncClient;
|
||||
import org.jclouds.aws.ec2.services.TagAsyncClient;
|
||||
import org.jclouds.ec2.EC2AsyncClient;
|
||||
import org.jclouds.rest.annotations.Delegate;
|
||||
|
||||
|
@ -82,10 +81,4 @@ public interface AWSEC2AsyncClient extends EC2AsyncClient {
|
|||
*/
|
||||
@Delegate
|
||||
SpotInstanceAsyncClient getSpotInstanceServices();
|
||||
|
||||
/**
|
||||
* Provides asynchronous access to SpotInstance services.
|
||||
*/
|
||||
@Delegate
|
||||
TagAsyncClient getTagServices();
|
||||
}
|
||||
|
|
|
@ -25,7 +25,6 @@ import org.jclouds.aws.ec2.services.AWSSecurityGroupClient;
|
|||
import org.jclouds.aws.ec2.services.MonitoringClient;
|
||||
import org.jclouds.aws.ec2.services.PlacementGroupClient;
|
||||
import org.jclouds.aws.ec2.services.SpotInstanceClient;
|
||||
import org.jclouds.aws.ec2.services.TagClient;
|
||||
import org.jclouds.ec2.EC2Client;
|
||||
import org.jclouds.rest.annotations.Delegate;
|
||||
|
||||
|
@ -81,10 +80,4 @@ public interface AWSEC2Client extends EC2Client {
|
|||
*/
|
||||
@Delegate
|
||||
SpotInstanceClient getSpotInstanceServices();
|
||||
|
||||
/**
|
||||
* Provides synchronous access to Tag services.
|
||||
*/
|
||||
@Delegate
|
||||
TagClient getTagServices();
|
||||
}
|
||||
|
|
|
@ -18,13 +18,11 @@
|
|||
*/
|
||||
package org.jclouds.aws.ec2.compute;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
import static com.google.common.base.Preconditions.checkState;
|
||||
import static com.google.common.collect.Iterables.transform;
|
||||
import static org.jclouds.aws.ec2.reference.AWSEC2Constants.PROPERTY_EC2_GENERATE_INSTANCE_NAMES;
|
||||
import static org.jclouds.compute.config.ComputeServiceProperties.TIMEOUT_NODE_RUNNING;
|
||||
import static org.jclouds.compute.config.ComputeServiceProperties.TIMEOUT_NODE_SUSPENDED;
|
||||
import static org.jclouds.compute.config.ComputeServiceProperties.TIMEOUT_NODE_TERMINATED;
|
||||
import static org.jclouds.ec2.reference.EC2Constants.PROPERTY_EC2_GENERATE_INSTANCE_NAMES;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
@ -38,20 +36,15 @@ import javax.inject.Provider;
|
|||
import javax.inject.Singleton;
|
||||
|
||||
import org.jclouds.Constants;
|
||||
import org.jclouds.aws.ec2.AWSEC2AsyncClient;
|
||||
import org.jclouds.aws.ec2.AWSEC2Client;
|
||||
import org.jclouds.aws.ec2.domain.PlacementGroup;
|
||||
import org.jclouds.aws.ec2.domain.PlacementGroup.State;
|
||||
import org.jclouds.aws.util.AWSUtils;
|
||||
import org.jclouds.collect.Memoized;
|
||||
import org.jclouds.compute.ComputeServiceContext;
|
||||
import org.jclouds.compute.RunNodesException;
|
||||
import org.jclouds.compute.callables.RunScriptOnNode;
|
||||
import org.jclouds.compute.domain.Hardware;
|
||||
import org.jclouds.compute.domain.Image;
|
||||
import org.jclouds.compute.domain.NodeMetadata;
|
||||
import org.jclouds.compute.domain.NodeMetadataBuilder;
|
||||
import org.jclouds.compute.domain.Template;
|
||||
import org.jclouds.compute.domain.TemplateBuilder;
|
||||
import org.jclouds.compute.extensions.ImageExtension;
|
||||
import org.jclouds.compute.functions.GroupNamingConvention;
|
||||
|
@ -71,20 +64,15 @@ import org.jclouds.domain.Credentials;
|
|||
import org.jclouds.domain.Location;
|
||||
import org.jclouds.ec2.compute.EC2ComputeService;
|
||||
import org.jclouds.ec2.compute.domain.RegionAndName;
|
||||
import org.jclouds.ec2.compute.options.EC2TemplateOptions;
|
||||
import org.jclouds.ec2.domain.KeyPair;
|
||||
import org.jclouds.scriptbuilder.functions.InitAdminAccess;
|
||||
import org.jclouds.util.Preconditions2;
|
||||
|
||||
import com.google.common.annotations.VisibleForTesting;
|
||||
import com.google.common.base.Function;
|
||||
import com.google.common.base.Optional;
|
||||
import com.google.common.base.Predicate;
|
||||
import com.google.common.base.Supplier;
|
||||
import com.google.common.cache.LoadingCache;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import com.google.common.collect.Iterables;
|
||||
|
||||
/**
|
||||
* @author Adrian Cole
|
||||
|
@ -94,9 +82,7 @@ public class AWSEC2ComputeService extends EC2ComputeService {
|
|||
|
||||
private final LoadingCache<RegionAndName, String> placementGroupMap;
|
||||
private final Predicate<PlacementGroup> placementGroupDeleted;
|
||||
private final AWSEC2Client ec2Client;
|
||||
private final AWSEC2AsyncClient aclient;
|
||||
private final boolean generateInstanceNames;
|
||||
private final AWSEC2Client client;
|
||||
|
||||
@Inject
|
||||
protected AWSEC2ComputeService(ComputeServiceContext context, Map<String, Credentials> credentialStore,
|
||||
|
@ -113,77 +99,22 @@ public class AWSEC2ComputeService extends EC2ComputeService {
|
|||
InitializeRunScriptOnNodeOrPlaceInBadMap.Factory initScriptRunnerFactory,
|
||||
RunScriptOnNode.Factory runScriptOnNodeFactory, InitAdminAccess initAdminAccess,
|
||||
PersistNodeCredentials persistNodeCredentials, Timeouts timeouts,
|
||||
@Named(Constants.PROPERTY_USER_THREADS) ExecutorService executor, AWSEC2Client ec2Client,
|
||||
@Named(Constants.PROPERTY_USER_THREADS) ExecutorService executor, AWSEC2Client client,
|
||||
ConcurrentMap<RegionAndName, KeyPair> credentialsMap,
|
||||
@Named("SECURITY") LoadingCache<RegionAndName, String> securityGroupMap,
|
||||
@Named("PLACEMENT") LoadingCache<RegionAndName, String> placementGroupMap,
|
||||
@Named("DELETED") Predicate<PlacementGroup> placementGroupDeleted,
|
||||
@Named(PROPERTY_EC2_GENERATE_INSTANCE_NAMES) boolean generateInstanceNames, AWSEC2AsyncClient aclient,
|
||||
Optional<ImageExtension> imageExtension, GroupNamingConvention.Factory namingConvention) {
|
||||
super(context, credentialStore, images, sizes, locations, listNodesStrategy, getImageStrategy, getNodeMetadataStrategy,
|
||||
runNodesAndAddToSetStrategy, rebootNodeStrategy, destroyNodeStrategy, startNodeStrategy,
|
||||
stopNodeStrategy, templateBuilderProvider, templateOptionsProvider, nodeRunning, nodeTerminated,
|
||||
nodeSuspended, initScriptRunnerFactory, runScriptOnNodeFactory, initAdminAccess, persistNodeCredentials,
|
||||
timeouts, executor, ec2Client, credentialsMap, securityGroupMap, imageExtension, namingConvention);
|
||||
this.ec2Client = ec2Client;
|
||||
@Named("DELETED") Predicate<PlacementGroup> placementGroupDeleted, Optional<ImageExtension> imageExtension,
|
||||
GroupNamingConvention.Factory namingConvention,
|
||||
@Named(PROPERTY_EC2_GENERATE_INSTANCE_NAMES) boolean generateInstanceNames) {
|
||||
super(context, credentialStore, images, sizes, locations, listNodesStrategy, getImageStrategy,
|
||||
getNodeMetadataStrategy, runNodesAndAddToSetStrategy, rebootNodeStrategy, destroyNodeStrategy,
|
||||
startNodeStrategy, stopNodeStrategy, templateBuilderProvider, templateOptionsProvider, nodeRunning,
|
||||
nodeTerminated, nodeSuspended, initScriptRunnerFactory, runScriptOnNodeFactory, initAdminAccess,
|
||||
persistNodeCredentials, timeouts, executor, client, credentialsMap, securityGroupMap, imageExtension,
|
||||
namingConvention, generateInstanceNames);
|
||||
this.client = client;
|
||||
this.placementGroupMap = placementGroupMap;
|
||||
this.placementGroupDeleted = placementGroupDeleted;
|
||||
this.generateInstanceNames = generateInstanceNames;
|
||||
this.aclient = checkNotNull(aclient, "aclient");
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<? extends NodeMetadata> createNodesInGroup(String group, int count, final Template template)
|
||||
throws RunNodesException {
|
||||
Set<? extends NodeMetadata> nodes = super.createNodesInGroup(group, count, template);
|
||||
// tags from spot requests do not propagate to running instances
|
||||
// automatically
|
||||
if (templateWasASpotRequestWithUserMetadata(template)) {
|
||||
addTagsToNodesFromUserMetadataInTemplate(nodes, group, template);
|
||||
nodes = addUserMetadataFromTemplateOptionsToNodes(template, group, nodes);
|
||||
}
|
||||
return nodes;
|
||||
}
|
||||
|
||||
protected void addTagsToNodesFromUserMetadataInTemplate(Set<? extends NodeMetadata> nodes, String group,
|
||||
final Template template) {
|
||||
String region = AWSUtils.getRegionFromLocationOrNull(template.getLocation());
|
||||
if (template.getOptions().getUserMetadata().size() > 0 || generateInstanceNames) {
|
||||
for (String id : transform(nodes, new Function<NodeMetadata, String>() {
|
||||
|
||||
@Override
|
||||
public String apply(NodeMetadata arg0) {
|
||||
return arg0.getProviderId();
|
||||
}
|
||||
|
||||
}))
|
||||
aclient.getTagServices().createTagsInRegion(region, ImmutableSet.of(id),
|
||||
metadataForId(id, group, template.getOptions().getUserMetadata()));
|
||||
}
|
||||
}
|
||||
|
||||
private Map<String, String> metadataForId(String id, String group, Map<String, String> metadata) {
|
||||
return generateInstanceNames && !metadata.containsKey("Name") ? ImmutableMap.<String, String> builder().putAll(
|
||||
metadata).put("Name", id.replaceAll(".*-", group + "-")).build() : metadata;
|
||||
}
|
||||
|
||||
protected boolean templateWasASpotRequestWithUserMetadata(final Template template) {
|
||||
return template.getOptions().getUserMetadata().size() > 0
|
||||
&& AWSEC2TemplateOptions.class.cast(template.getOptions()).getSpotPrice() != null;
|
||||
}
|
||||
|
||||
protected Set<? extends NodeMetadata> addUserMetadataFromTemplateOptionsToNodes(final Template template,
|
||||
final String group, Set<? extends NodeMetadata> nodes) {
|
||||
nodes = ImmutableSet.copyOf(Iterables.transform(nodes, new Function<NodeMetadata, NodeMetadata>() {
|
||||
|
||||
@Override
|
||||
public NodeMetadata apply(NodeMetadata arg0) {
|
||||
Map<String, String> md = metadataForId(arg0.getProviderId(), group, template.getOptions().getUserMetadata());
|
||||
return NodeMetadataBuilder.fromNodeMetadata(arg0).name(md.get("Name")).userMetadata(md).build();
|
||||
}
|
||||
|
||||
}));
|
||||
return nodes;
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
|
@ -193,10 +124,10 @@ public class AWSEC2ComputeService extends EC2ComputeService {
|
|||
// http://docs.amazonwebservices.com/AWSEC2/latest/UserGuide/index.html?using_cluster_computing.html
|
||||
String placementGroup = String.format("jclouds#%s#%s", group, region);
|
||||
try {
|
||||
if (ec2Client.getPlacementGroupServices().describePlacementGroupsInRegion(region, placementGroup).size() > 0) {
|
||||
if (client.getPlacementGroupServices().describePlacementGroupsInRegion(region, placementGroup).size() > 0) {
|
||||
logger.debug(">> deleting placementGroup(%s)", placementGroup);
|
||||
try {
|
||||
ec2Client.getPlacementGroupServices().deletePlacementGroupInRegion(region, placementGroup);
|
||||
client.getPlacementGroupServices().deletePlacementGroupInRegion(region, placementGroup);
|
||||
checkState(placementGroupDeleted.apply(new PlacementGroup(region, placementGroup, "cluster",
|
||||
State.PENDING)), String.format("placementGroup region(%s) name(%s) failed to delete", region,
|
||||
placementGroup));
|
||||
|
@ -218,11 +149,11 @@ public class AWSEC2ComputeService extends EC2ComputeService {
|
|||
}
|
||||
|
||||
/**
|
||||
* returns template options, except of type {@link EC2TemplateOptions}.
|
||||
* returns template options, except of type {@link AWSEC2TemplateOptions}.
|
||||
*/
|
||||
@Override
|
||||
public EC2TemplateOptions templateOptions() {
|
||||
return EC2TemplateOptions.class.cast(super.templateOptions());
|
||||
public AWSEC2TemplateOptions templateOptions() {
|
||||
return AWSEC2TemplateOptions.class.cast(super.templateOptions());
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -30,7 +30,7 @@ import javax.inject.Singleton;
|
|||
|
||||
import org.jclouds.aws.ec2.compute.AWSEC2TemplateBuilderImpl;
|
||||
import org.jclouds.aws.ec2.compute.functions.AWSRunningInstanceToNodeMetadata;
|
||||
import org.jclouds.aws.ec2.compute.predicates.AWSEC2InstancePresent;
|
||||
import org.jclouds.aws.ec2.compute.functions.PresentSpotRequestsAndInstances;
|
||||
import org.jclouds.aws.ec2.compute.strategy.AWSEC2CreateNodesInGroupThenAddToSet;
|
||||
import org.jclouds.aws.ec2.compute.strategy.AWSEC2DestroyNodeStrategy;
|
||||
import org.jclouds.aws.ec2.compute.strategy.AWSEC2GetNodeMetadataStrategy;
|
||||
|
@ -44,11 +44,11 @@ import org.jclouds.compute.extensions.ImageExtension;
|
|||
import org.jclouds.compute.options.TemplateOptions;
|
||||
import org.jclouds.ec2.compute.config.EC2BindComputeStrategiesByClass;
|
||||
import org.jclouds.ec2.compute.domain.RegionAndName;
|
||||
import org.jclouds.ec2.compute.functions.PresentInstances;
|
||||
import org.jclouds.ec2.compute.functions.RunningInstanceToNodeMetadata;
|
||||
import org.jclouds.ec2.compute.internal.EC2TemplateBuilderImpl;
|
||||
import org.jclouds.ec2.compute.loaders.RegionAndIdToImage;
|
||||
import org.jclouds.ec2.compute.options.EC2TemplateOptions;
|
||||
import org.jclouds.ec2.compute.predicates.InstancePresent;
|
||||
import org.jclouds.ec2.compute.strategy.CreateKeyPairAndSecurityGroupsAsNeededAndReturnRunOptions;
|
||||
import org.jclouds.ec2.compute.strategy.EC2CreateNodesInGroupThenAddToSet;
|
||||
import org.jclouds.ec2.compute.strategy.EC2DestroyNodeStrategy;
|
||||
|
@ -92,7 +92,7 @@ public class AWSEC2ComputeServiceContextModule extends BaseComputeServiceContext
|
|||
bind(EC2GetNodeMetadataStrategy.class).to(AWSEC2GetNodeMetadataStrategy.class);
|
||||
bind(EC2ListNodesStrategy.class).to(AWSEC2ListNodesStrategy.class);
|
||||
bind(EC2DestroyNodeStrategy.class).to(AWSEC2DestroyNodeStrategy.class);
|
||||
bind(InstancePresent.class).to(AWSEC2InstancePresent.class);
|
||||
bind(PresentInstances.class).to(PresentSpotRequestsAndInstances.class);
|
||||
bind(EC2CreateNodesInGroupThenAddToSet.class).to(AWSEC2CreateNodesInGroupThenAddToSet.class);
|
||||
bind(RunningInstanceToNodeMetadata.class).to(AWSRunningInstanceToNodeMetadata.class);
|
||||
}
|
||||
|
|
|
@ -18,8 +18,6 @@
|
|||
*/
|
||||
package org.jclouds.aws.ec2.compute.functions;
|
||||
|
||||
import static org.jclouds.compute.util.ComputeServiceUtils.addMetadataAndParseTagsFromValuesOfEmptyString;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
|
@ -31,8 +29,8 @@ import org.jclouds.collect.Memoized;
|
|||
import org.jclouds.compute.domain.Hardware;
|
||||
import org.jclouds.compute.domain.HardwareBuilder;
|
||||
import org.jclouds.compute.domain.Image;
|
||||
import org.jclouds.compute.domain.NodeMetadataBuilder;
|
||||
import org.jclouds.compute.domain.NodeMetadata.Status;
|
||||
import org.jclouds.compute.domain.NodeMetadataBuilder;
|
||||
import org.jclouds.compute.functions.GroupNamingConvention;
|
||||
import org.jclouds.domain.Credentials;
|
||||
import org.jclouds.domain.Location;
|
||||
|
@ -82,11 +80,4 @@ public class AWSRunningInstanceToNodeMetadata extends RunningInstanceToNodeMetad
|
|||
return HardwareBuilder.fromHardware(in).hypervisor(awsInstance.getHypervisor().toString()).build();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected NodeMetadataBuilder buildInstance(RunningInstance instance, NodeMetadataBuilder builder) {
|
||||
AWSRunningInstance awsInstance = AWSRunningInstance.class.cast(instance);
|
||||
builder.name(awsInstance.getTags().get("Name"));
|
||||
addMetadataAndParseTagsFromValuesOfEmptyString(builder, awsInstance.getTags());
|
||||
return super.buildInstance(instance, builder);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,96 @@
|
|||
/**
|
||||
* Licensed to jclouds, Inc. (jclouds) under one or more
|
||||
* contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. jclouds 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.jclouds.aws.ec2.compute.functions;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
import static com.google.common.base.Predicates.compose;
|
||||
import static com.google.common.base.Predicates.containsPattern;
|
||||
import static com.google.common.collect.Iterables.any;
|
||||
import static com.google.common.collect.Iterables.toArray;
|
||||
import static com.google.common.collect.Iterables.transform;
|
||||
import static com.google.common.collect.Multimaps.index;
|
||||
import static com.google.common.collect.Multimaps.transformValues;
|
||||
import static org.jclouds.ec2.compute.domain.RegionAndName.nameFunction;
|
||||
import static org.jclouds.ec2.compute.domain.RegionAndName.regionFunction;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Set;
|
||||
|
||||
import javax.inject.Singleton;
|
||||
|
||||
import org.jclouds.aws.ec2.AWSEC2Client;
|
||||
import org.jclouds.aws.ec2.domain.AWSRunningInstance;
|
||||
import org.jclouds.aws.ec2.domain.SpotInstanceRequest;
|
||||
import org.jclouds.aws.ec2.functions.SpotInstanceRequestToAWSRunningInstance;
|
||||
import org.jclouds.ec2.compute.domain.RegionAndName;
|
||||
import org.jclouds.ec2.compute.functions.PresentInstances;
|
||||
import org.jclouds.ec2.domain.RunningInstance;
|
||||
|
||||
import com.google.common.base.Function;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import com.google.common.collect.ImmutableSet.Builder;
|
||||
import com.google.common.collect.Multimap;
|
||||
import com.google.inject.Inject;
|
||||
|
||||
/**
|
||||
* returns either the instances present in the list, or spot instances, if they ids start with {@code sir-}. Makes a
|
||||
* single rest call per aggregate on region.
|
||||
*
|
||||
* @author Adrian Cole
|
||||
*/
|
||||
@Singleton
|
||||
public class PresentSpotRequestsAndInstances extends PresentInstances {
|
||||
|
||||
private final AWSEC2Client client;
|
||||
private final Function<SpotInstanceRequest, AWSRunningInstance> spotConverter;
|
||||
|
||||
@Inject
|
||||
public PresentSpotRequestsAndInstances(AWSEC2Client client, Function<SpotInstanceRequest, AWSRunningInstance> spotConverter) {
|
||||
super(client);
|
||||
this.client = checkNotNull(client, "client");
|
||||
this.spotConverter = checkNotNull(spotConverter, "spotConverter");
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<RunningInstance> apply(Set<RegionAndName> regionAndIds) {
|
||||
if (checkNotNull(regionAndIds, "regionAndIds").isEmpty())
|
||||
return ImmutableSet.of();
|
||||
if (any(regionAndIds, compose(containsPattern("sir-"), nameFunction())))
|
||||
return getSpots(regionAndIds);
|
||||
return super.apply(regionAndIds);
|
||||
}
|
||||
|
||||
protected Set<RunningInstance> getSpots(Set<RegionAndName> regionAndIds) {
|
||||
Builder<RunningInstance> builder = ImmutableSet.<RunningInstance> builder();
|
||||
Multimap<String, String> regionToSpotIds = transformValues(index(regionAndIds, regionFunction()), nameFunction());
|
||||
for (String region : regionToSpotIds.keySet()) {
|
||||
Collection<String> spotIds = regionToSpotIds.get(region);
|
||||
logger.trace("looking for spots %s in region %s", spotIds, region);
|
||||
builder.addAll(transform(
|
||||
client.getSpotInstanceServices().describeSpotInstanceRequestsInRegion(region,
|
||||
toArray(spotIds, String.class)), spotConverter));
|
||||
}
|
||||
return builder.build();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "presentSpotRequestsAndInstances()";
|
||||
}
|
||||
}
|
|
@ -1,55 +0,0 @@
|
|||
/**
|
||||
* Licensed to jclouds, Inc. (jclouds) under one or more
|
||||
* contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. jclouds 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.jclouds.aws.ec2.compute.predicates;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
|
||||
import javax.inject.Singleton;
|
||||
|
||||
import org.jclouds.aws.ec2.AWSEC2Client;
|
||||
import org.jclouds.ec2.compute.domain.RegionAndName;
|
||||
import org.jclouds.ec2.compute.predicates.InstancePresent;
|
||||
|
||||
import com.google.common.collect.Iterables;
|
||||
import com.google.inject.Inject;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Adrian Cole
|
||||
*/
|
||||
@Singleton
|
||||
public class AWSEC2InstancePresent extends InstancePresent {
|
||||
|
||||
private final AWSEC2Client client;
|
||||
|
||||
@Inject
|
||||
public AWSEC2InstancePresent(AWSEC2Client client) {
|
||||
super(client);
|
||||
this.client = checkNotNull(client, "client");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void refresh(RegionAndName instance) {
|
||||
if (instance.getName().indexOf("sir-") != 0)
|
||||
super.refresh(instance);
|
||||
else
|
||||
Iterables.getOnlyElement(client.getSpotInstanceServices().describeSpotInstanceRequestsInRegion(
|
||||
instance.getRegion(), instance.getName()));
|
||||
}
|
||||
}
|
|
@ -19,30 +19,27 @@
|
|||
package org.jclouds.aws.ec2.compute.strategy;
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
import static com.google.common.collect.Iterables.transform;
|
||||
import static org.jclouds.aws.ec2.reference.AWSEC2Constants.PROPERTY_EC2_GENERATE_INSTANCE_NAMES;
|
||||
import static org.jclouds.compute.config.ComputeServiceProperties.TIMEOUT_NODE_RUNNING;
|
||||
import static org.jclouds.compute.util.ComputeServiceUtils.metadataAndTagsAsValuesOfEmptyString;
|
||||
import static org.jclouds.ec2.reference.EC2Constants.PROPERTY_EC2_GENERATE_INSTANCE_NAMES;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Named;
|
||||
import javax.inject.Provider;
|
||||
import javax.inject.Singleton;
|
||||
|
||||
import org.jclouds.aws.ec2.AWSEC2AsyncClient;
|
||||
import org.jclouds.aws.ec2.AWSEC2Client;
|
||||
import org.jclouds.aws.ec2.compute.AWSEC2TemplateOptions;
|
||||
import org.jclouds.aws.ec2.compute.predicates.AWSEC2InstancePresent;
|
||||
import org.jclouds.aws.ec2.compute.functions.PresentSpotRequestsAndInstances;
|
||||
import org.jclouds.aws.ec2.domain.LaunchSpecification;
|
||||
import org.jclouds.aws.ec2.functions.SpotInstanceRequestToAWSRunningInstance;
|
||||
import org.jclouds.aws.ec2.options.AWSRunInstancesOptions;
|
||||
import org.jclouds.aws.ec2.options.RequestSpotInstancesOptions;
|
||||
import org.jclouds.compute.domain.NodeMetadata;
|
||||
import org.jclouds.compute.domain.Template;
|
||||
import org.jclouds.compute.domain.TemplateBuilder;
|
||||
import org.jclouds.compute.options.TemplateOptions;
|
||||
import org.jclouds.compute.reference.ComputeServiceConstants;
|
||||
import org.jclouds.compute.util.ComputeUtils;
|
||||
|
@ -58,7 +55,6 @@ import com.google.common.annotations.VisibleForTesting;
|
|||
import com.google.common.base.Function;
|
||||
import com.google.common.base.Predicate;
|
||||
import com.google.common.cache.LoadingCache;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
|
||||
/**
|
||||
|
@ -70,39 +66,33 @@ public class AWSEC2CreateNodesInGroupThenAddToSet extends EC2CreateNodesInGroupT
|
|||
|
||||
@Resource
|
||||
@Named(ComputeServiceConstants.COMPUTE_LOGGER)
|
||||
protected Logger logger = Logger.NULL;
|
||||
private Logger logger = Logger.NULL;
|
||||
|
||||
@VisibleForTesting
|
||||
final AWSEC2Client client;
|
||||
final SpotInstanceRequestToAWSRunningInstance spotConverter;
|
||||
final AWSEC2AsyncClient aclient;
|
||||
final boolean generateInstanceNames;
|
||||
private final AWSEC2Client client;
|
||||
private final SpotInstanceRequestToAWSRunningInstance spotConverter;
|
||||
|
||||
@Inject
|
||||
protected AWSEC2CreateNodesInGroupThenAddToSet(
|
||||
AWSEC2Client client,
|
||||
@Named("ELASTICIP") LoadingCache<RegionAndName, String> elasticIpCache,
|
||||
@Named(TIMEOUT_NODE_RUNNING) Predicate<AtomicReference<NodeMetadata>> nodeRunning,
|
||||
AWSEC2AsyncClient aclient,
|
||||
@Named(PROPERTY_EC2_GENERATE_INSTANCE_NAMES) boolean generateInstanceNames,
|
||||
Provider<TemplateBuilder> templateBuilderProvider,
|
||||
CreateKeyPairPlacementAndSecurityGroupsAsNeededAndReturnRunOptions createKeyPairAndSecurityGroupsAsNeededAndReturncustomize,
|
||||
AWSEC2InstancePresent instancePresent,
|
||||
PresentSpotRequestsAndInstances instancePresent,
|
||||
Function<RunningInstance, NodeMetadata> runningInstanceToNodeMetadata,
|
||||
LoadingCache<RunningInstance, LoginCredentials> instanceToCredentials, Map<String, Credentials> credentialStore,
|
||||
ComputeUtils utils, SpotInstanceRequestToAWSRunningInstance spotConverter) {
|
||||
super(client, elasticIpCache, nodeRunning, templateBuilderProvider, createKeyPairAndSecurityGroupsAsNeededAndReturncustomize,
|
||||
LoadingCache<RunningInstance, LoginCredentials> instanceToCredentials,
|
||||
Map<String, Credentials> credentialStore, ComputeUtils utils,
|
||||
SpotInstanceRequestToAWSRunningInstance spotConverter) {
|
||||
super(client, elasticIpCache, nodeRunning, createKeyPairAndSecurityGroupsAsNeededAndReturncustomize,
|
||||
instancePresent, runningInstanceToNodeMetadata, instanceToCredentials, credentialStore, utils);
|
||||
this.client = checkNotNull(client, "client");
|
||||
this.aclient = checkNotNull(aclient, "aclient");
|
||||
this.spotConverter = checkNotNull(spotConverter, "spotConverter");
|
||||
this.generateInstanceNames = generateInstanceNames;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Iterable<? extends RunningInstance> createNodesInRegionAndZone(String region, String zone, String group,
|
||||
protected Set<RunningInstance> createNodesInRegionAndZone(String region, String zone, String group,
|
||||
int count, Template template, RunInstancesOptions instanceOptions) {
|
||||
Map<String, String> tags = metadataAndTagsAsValuesOfEmptyString(template.getOptions());
|
||||
Float spotPrice = getSpotPriceOrNull(template.getOptions());
|
||||
if (spotPrice != null) {
|
||||
LaunchSpecification spec = AWSRunInstancesOptions.class.cast(instanceOptions).getLaunchSpecificationBuilder()
|
||||
|
@ -111,36 +101,10 @@ public class AWSEC2CreateNodesInGroupThenAddToSet extends EC2CreateNodesInGroupT
|
|||
if (logger.isDebugEnabled())
|
||||
logger.debug(">> requesting %d spot instances region(%s) price(%f) spec(%s) options(%s)", count, region,
|
||||
spotPrice, spec, options);
|
||||
return addTagsToInstancesInRegion(tags, transform(client
|
||||
.getSpotInstanceServices().requestSpotInstancesInRegion(region, spotPrice, count, spec, options),
|
||||
spotConverter), region, group);
|
||||
} else {
|
||||
return addTagsToInstancesInRegion(tags, super.createNodesInRegionAndZone(
|
||||
region, zone, group, count, template, instanceOptions), region, group);
|
||||
return ImmutableSet.<RunningInstance> copyOf(transform(client.getSpotInstanceServices()
|
||||
.requestSpotInstancesInRegion(region, spotPrice, count, spec, options), spotConverter));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public Iterable<? extends RunningInstance> addTagsToInstancesInRegion(Map<String, String> metadata,
|
||||
Iterable<? extends RunningInstance> iterable, String region, String group) {
|
||||
if (metadata.size() > 0 || generateInstanceNames) {
|
||||
for (String id : transform(iterable, new Function<RunningInstance, String>() {
|
||||
|
||||
@Override
|
||||
public String apply(RunningInstance arg0) {
|
||||
return arg0.getId();
|
||||
}
|
||||
|
||||
}))
|
||||
aclient.getTagServices()
|
||||
.createTagsInRegion(region, ImmutableSet.of(id), metadataForId(id, group, metadata));
|
||||
}
|
||||
return iterable;
|
||||
}
|
||||
|
||||
private Map<String, String> metadataForId(String id, String group, Map<String, String> metadata) {
|
||||
return generateInstanceNames && !metadata.containsKey("Name") ? ImmutableMap.<String, String> builder().putAll(
|
||||
metadata).put("Name", id.replaceAll(".*-", group + "-")).build() : metadata;
|
||||
return super.createNodesInRegionAndZone(region, zone, group, count, template, instanceOptions);
|
||||
}
|
||||
|
||||
private Float getSpotPriceOrNull(TemplateOptions options) {
|
||||
|
|
|
@ -25,6 +25,8 @@ import javax.inject.Singleton;
|
|||
import org.jclouds.aws.ec2.AWSEC2AsyncClient;
|
||||
import org.jclouds.aws.ec2.AWSEC2Client;
|
||||
import org.jclouds.aws.ec2.domain.AWSRunningInstance;
|
||||
import org.jclouds.aws.ec2.domain.SpotInstanceRequest;
|
||||
import org.jclouds.aws.ec2.functions.SpotInstanceRequestToAWSRunningInstance;
|
||||
import org.jclouds.aws.ec2.options.AWSRunInstancesOptions;
|
||||
import org.jclouds.aws.ec2.services.AWSAMIAsyncClient;
|
||||
import org.jclouds.aws.ec2.services.AWSAMIClient;
|
||||
|
@ -40,12 +42,9 @@ import org.jclouds.aws.ec2.services.PlacementGroupAsyncClient;
|
|||
import org.jclouds.aws.ec2.services.PlacementGroupClient;
|
||||
import org.jclouds.aws.ec2.services.SpotInstanceAsyncClient;
|
||||
import org.jclouds.aws.ec2.services.SpotInstanceClient;
|
||||
import org.jclouds.aws.ec2.services.TagAsyncClient;
|
||||
import org.jclouds.aws.ec2.services.TagClient;
|
||||
import org.jclouds.ec2.EC2AsyncClient;
|
||||
import org.jclouds.ec2.EC2Client;
|
||||
import org.jclouds.ec2.config.EC2RestClientModule;
|
||||
import org.jclouds.ec2.domain.RunningInstance;
|
||||
import org.jclouds.ec2.features.TagApi;
|
||||
import org.jclouds.ec2.features.TagAsyncApi;
|
||||
import org.jclouds.ec2.features.WindowsApi;
|
||||
|
@ -67,9 +66,11 @@ import org.jclouds.ec2.services.WindowsAsyncClient;
|
|||
import org.jclouds.ec2.services.WindowsClient;
|
||||
import org.jclouds.rest.ConfiguresRestClient;
|
||||
|
||||
import com.google.common.base.Function;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import com.google.common.reflect.TypeToken;
|
||||
import com.google.inject.Provides;
|
||||
import com.google.inject.TypeLiteral;
|
||||
|
||||
/**
|
||||
* Configures the EC2 connection.
|
||||
|
@ -91,7 +92,6 @@ public class AWSEC2RestClientModule extends EC2RestClientModule<AWSEC2Client, AW
|
|||
.put(AvailabilityZoneAndRegionClient.class, AvailabilityZoneAndRegionAsyncClient.class)//
|
||||
.put(ElasticBlockStoreClient.class, ElasticBlockStoreAsyncClient.class)//
|
||||
.put(SpotInstanceClient.class, SpotInstanceAsyncClient.class)//
|
||||
.put(TagClient.class, TagAsyncClient.class)//
|
||||
.put(WindowsApi.class, WindowsAsyncApi.class)//
|
||||
.put(TagApi.class, TagAsyncApi.class)//
|
||||
.build();
|
||||
|
@ -148,22 +148,11 @@ public class AWSEC2RestClientModule extends EC2RestClientModule<AWSEC2Client, AW
|
|||
return in.getAMIServices();
|
||||
}
|
||||
|
||||
@Singleton
|
||||
@Provides
|
||||
TagClient getTagServices(AWSEC2Client in) {
|
||||
return in.getTagServices();
|
||||
}
|
||||
|
||||
@Singleton
|
||||
@Provides
|
||||
TagAsyncClient getTagServices(AWSEC2AsyncClient in) {
|
||||
return in.getTagServices();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void configure() {
|
||||
bind(RunningInstance.Builder.class).to(AWSRunningInstance.Builder.class);
|
||||
bind(RunInstancesOptions.class).to(AWSRunInstancesOptions.class);
|
||||
bind(new TypeLiteral<Function<SpotInstanceRequest, AWSRunningInstance>>() {
|
||||
}).to(SpotInstanceRequestToAWSRunningInstance.class);
|
||||
super.configure();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -32,7 +32,6 @@ import org.jclouds.ec2.domain.RunningInstance;
|
|||
import org.jclouds.javax.annotation.Nullable;
|
||||
|
||||
import com.google.common.base.Objects.ToStringHelper;
|
||||
import com.google.common.base.Strings;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import com.google.common.collect.Maps;
|
||||
|
@ -46,11 +45,17 @@ import com.google.common.collect.Sets;
|
|||
* @author Adrian Cole
|
||||
*/
|
||||
public class AWSRunningInstance extends RunningInstance {
|
||||
|
||||
public static Builder builder() {
|
||||
return new Builder();
|
||||
}
|
||||
|
||||
public static class Builder extends org.jclouds.ec2.domain.RunningInstance.Builder {
|
||||
@Override
|
||||
public Builder toBuilder() {
|
||||
return new Builder().fromRunningInstance(this);
|
||||
}
|
||||
|
||||
public static class Builder extends org.jclouds.ec2.domain.RunningInstance.Builder<Builder> {
|
||||
private MonitoringState monitoringState;
|
||||
private String placementGroup;
|
||||
private Set<String> productCodes = Sets.newLinkedHashSet();
|
||||
|
@ -59,18 +64,6 @@ public class AWSRunningInstance extends RunningInstance {
|
|||
private String vpcId;
|
||||
private Hypervisor hypervisor;
|
||||
private Map<String, String> securityGroupIdToNames = Maps.newLinkedHashMap();
|
||||
private Map<String, String> tags = Maps.newLinkedHashMap();
|
||||
|
||||
public Builder tags(Map<String, String> tags) {
|
||||
this.tags = ImmutableMap.copyOf(checkNotNull(tags, "tags"));
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder tag(String key, String value) {
|
||||
if (key != null)
|
||||
this.tags.put(key, Strings.nullToEmpty(value));
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder securityGroupIdToNames(Map<String, String> securityGroupIdToNames) {
|
||||
this.securityGroupIdToNames = ImmutableMap.copyOf(checkNotNull(securityGroupIdToNames,
|
||||
|
@ -125,131 +118,6 @@ public class AWSRunningInstance extends RunningInstance {
|
|||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Builder amiLaunchIndex(String amiLaunchIndex) {
|
||||
return Builder.class.cast(super.amiLaunchIndex(amiLaunchIndex));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Builder availabilityZone(String availabilityZone) {
|
||||
return Builder.class.cast(super.availabilityZone(availabilityZone));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Builder devices(Map<String, BlockDevice> ebsBlockDevices) {
|
||||
return Builder.class.cast(super.devices(ebsBlockDevices));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Builder dnsName(String dnsName) {
|
||||
return Builder.class.cast(super.dnsName(dnsName));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Builder imageId(String imageId) {
|
||||
return Builder.class.cast(super.imageId(imageId));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Builder instanceId(String instanceId) {
|
||||
return Builder.class.cast(super.instanceId(instanceId));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Builder instanceState(InstanceState instanceState) {
|
||||
return Builder.class.cast(super.instanceState(instanceState));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Builder rawState(String rawState) {
|
||||
return Builder.class.cast(super.rawState(rawState));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Builder instanceType(String instanceType) {
|
||||
return Builder.class.cast(super.instanceType(instanceType));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Builder ipAddress(String ipAddress) {
|
||||
return Builder.class.cast(super.ipAddress(ipAddress));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Builder kernelId(String kernelId) {
|
||||
return Builder.class.cast(super.kernelId(kernelId));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Builder keyName(String keyName) {
|
||||
return Builder.class.cast(super.keyName(keyName));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Builder launchTime(Date launchTime) {
|
||||
return Builder.class.cast(super.launchTime(launchTime));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Builder platform(String platform) {
|
||||
return Builder.class.cast(super.platform(platform));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Builder privateDnsName(String privateDnsName) {
|
||||
return Builder.class.cast(super.privateDnsName(privateDnsName));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Builder privateIpAddress(String privateIpAddress) {
|
||||
return Builder.class.cast(super.privateIpAddress(privateIpAddress));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Builder ramdiskId(String ramdiskId) {
|
||||
return Builder.class.cast(super.ramdiskId(ramdiskId));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Builder reason(String reason) {
|
||||
return Builder.class.cast(super.reason(reason));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Builder region(String region) {
|
||||
return Builder.class.cast(super.region(region));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Builder rootDeviceName(String rootDeviceName) {
|
||||
return Builder.class.cast(super.rootDeviceName(rootDeviceName));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Builder rootDeviceType(RootDeviceType rootDeviceType) {
|
||||
return Builder.class.cast(super.rootDeviceType(rootDeviceType));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Builder virtualizationType(String virtualizationType) {
|
||||
return Builder.class.cast(super.virtualizationType(virtualizationType));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Builder device(String key, BlockDevice value) {
|
||||
return Builder.class.cast(super.device(key, value));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Builder groupName(String groupName) {
|
||||
return Builder.class.cast(super.groupName(groupName));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Builder groupNames(Iterable<String> groupNames) {
|
||||
return Builder.class.cast(super.groupNames(groupNames));
|
||||
}
|
||||
|
||||
@Override
|
||||
public AWSRunningInstance build() {
|
||||
return new AWSRunningInstance(region, securityGroupIdToNames, amiLaunchIndex, dnsName, imageId, instanceId,
|
||||
|
@ -259,6 +127,24 @@ public class AWSRunningInstance extends RunningInstance {
|
|||
spotInstanceRequestId, vpcId, hypervisor, tags);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Builder fromRunningInstance(RunningInstance in) {
|
||||
super.fromRunningInstance(in);
|
||||
if (in instanceof AWSRunningInstance) {
|
||||
AWSRunningInstance awsIn = AWSRunningInstance.class.cast(in);
|
||||
monitoringState(awsIn.monitoringState).placementGroup(awsIn.placementGroup)
|
||||
.productCodes(awsIn.productCodes).subnetId(awsIn.subnetId)
|
||||
.spotInstanceRequestId(awsIn.spotInstanceRequestId).vpcId(awsIn.vpcId).hypervisor(awsIn.hypervisor)
|
||||
.securityGroupIdToNames(awsIn.securityGroupIdToNames);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Builder self() {
|
||||
return this;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private final MonitoringState monitoringState;
|
||||
|
@ -273,7 +159,6 @@ public class AWSRunningInstance extends RunningInstance {
|
|||
private final String vpcId;
|
||||
private final Hypervisor hypervisor;
|
||||
private final Map<String, String> securityGroupIdToNames;
|
||||
private final Map<String, String> tags;
|
||||
|
||||
protected AWSRunningInstance(String region, Map<String, String> securityGroupIdToNames, String amiLaunchIndex,
|
||||
String dnsName, String imageId, String instanceId, InstanceState instanceState, String rawState,
|
||||
|
@ -286,7 +171,7 @@ public class AWSRunningInstance extends RunningInstance {
|
|||
super(region, securityGroupIdToNames.values(), amiLaunchIndex, dnsName, imageId, instanceId, instanceState,
|
||||
rawState, instanceType, ipAddress, kernelId, keyName, launchTime, availabilityZone, virtualizationType,
|
||||
platform, privateDnsName, privateIpAddress, ramdiskId, reason, rootDeviceType, rootDeviceName,
|
||||
ebsBlockDevices);
|
||||
ebsBlockDevices, tags);
|
||||
this.monitoringState = checkNotNull(monitoringState, "monitoringState");
|
||||
this.placementGroup = placementGroup;
|
||||
this.productCodes = ImmutableSet.copyOf(checkNotNull(productCodes, "productCodes"));
|
||||
|
@ -296,7 +181,6 @@ public class AWSRunningInstance extends RunningInstance {
|
|||
this.hypervisor = checkNotNull(hypervisor, "hypervisor");
|
||||
this.securityGroupIdToNames = ImmutableMap.<String, String> copyOf(checkNotNull(securityGroupIdToNames,
|
||||
"securityGroupIdToNames"));
|
||||
this.tags = ImmutableMap.<String, String> copyOf(checkNotNull(tags, "tags"));
|
||||
}
|
||||
|
||||
public Map<String, String> getSecurityGroupIdToNames() {
|
||||
|
@ -356,18 +240,11 @@ public class AWSRunningInstance extends RunningInstance {
|
|||
return subnetId;
|
||||
}
|
||||
|
||||
/**
|
||||
* tags that are present in the instance
|
||||
*/
|
||||
public Map<String, String> getTags() {
|
||||
return tags;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ToStringHelper string() {
|
||||
return super.string().add("monitoringState", monitoringState).add("placementGroup", placementGroup)
|
||||
.add("subnetId", subnetId).add("spotInstanceRequestId", spotInstanceRequestId).add("vpcId", vpcId)
|
||||
.add("hypervisor", hypervisor).add("tags", tags);
|
||||
.add("hypervisor", hypervisor);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -18,8 +18,6 @@
|
|||
*/
|
||||
package org.jclouds.aws.ec2.functions;
|
||||
|
||||
import javax.inject.Singleton;
|
||||
|
||||
import org.jclouds.aws.ec2.domain.AWSRunningInstance;
|
||||
import org.jclouds.aws.ec2.domain.LaunchSpecification;
|
||||
import org.jclouds.aws.ec2.domain.MonitoringState;
|
||||
|
@ -32,7 +30,6 @@ import com.google.common.base.Function;
|
|||
/**
|
||||
* @author Adrian Cole
|
||||
*/
|
||||
@Singleton
|
||||
public class SpotInstanceRequestToAWSRunningInstance implements Function<SpotInstanceRequest, AWSRunningInstance> {
|
||||
|
||||
@Override
|
||||
|
|
|
@ -37,10 +37,5 @@ public interface AWSEC2Constants extends EC2Constants {
|
|||
public static final String PROPERTY_EC2_CC_AMI_QUERY = "jclouds.ec2.cc-ami-query";
|
||||
public static final String PROPERTY_EC2_CC_REGIONS = "jclouds.ec2.cc-regions";
|
||||
public static final String PROPERTY_EC2_AMI_QUERY = "jclouds.ec2.ami-query";
|
||||
/**
|
||||
* If this property is set to true(default), jclouds generate a name for each instance based on
|
||||
* the group. ex. i-ef34ae2 becomes hadoop-ef34ae2.
|
||||
*/
|
||||
public static final String PROPERTY_EC2_GENERATE_INSTANCE_NAMES = "jclouds.ec2.generate-instance-names";
|
||||
|
||||
}
|
||||
|
|
|
@ -1,97 +0,0 @@
|
|||
/**
|
||||
* Licensed to jclouds, Inc. (jclouds) under one or more
|
||||
* contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. jclouds 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.jclouds.aws.ec2.services;
|
||||
|
||||
import static org.jclouds.aws.reference.FormParameters.ACTION;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import javax.inject.Named;
|
||||
import javax.ws.rs.POST;
|
||||
import javax.ws.rs.Path;
|
||||
|
||||
import org.jclouds.Fallbacks.EmptySetOnNotFoundOr404;
|
||||
import org.jclouds.Fallbacks.VoidOnNotFoundOr404;
|
||||
import org.jclouds.aws.ec2.binders.BindTagFiltersToIndexedFormParams;
|
||||
import org.jclouds.aws.ec2.binders.BindTagsToIndexedFormParams;
|
||||
import org.jclouds.aws.ec2.domain.Tag;
|
||||
import org.jclouds.aws.ec2.util.TagFilters.FilterName;
|
||||
import org.jclouds.aws.ec2.xml.DescribeTagsResponseHandler;
|
||||
import org.jclouds.aws.filters.FormSigner;
|
||||
import org.jclouds.ec2.binders.BindResourceIdsToIndexedFormParams;
|
||||
import org.jclouds.javax.annotation.Nullable;
|
||||
import org.jclouds.location.functions.RegionToEndpointOrProviderIfNull;
|
||||
import org.jclouds.rest.annotations.BinderParam;
|
||||
import org.jclouds.rest.annotations.EndpointParam;
|
||||
import org.jclouds.rest.annotations.Fallback;
|
||||
import org.jclouds.rest.annotations.FormParams;
|
||||
import org.jclouds.rest.annotations.RequestFilters;
|
||||
import org.jclouds.rest.annotations.VirtualHost;
|
||||
import org.jclouds.rest.annotations.XMLResponseParser;
|
||||
|
||||
import com.google.common.util.concurrent.ListenableFuture;
|
||||
|
||||
/**
|
||||
* Provides access to EC2 Tags via their REST API.
|
||||
*
|
||||
* <h3>Important</h3>
|
||||
* This will be removed in jclouds version 1.6
|
||||
*
|
||||
* @author grkvlt@apache.org
|
||||
*/
|
||||
@Deprecated
|
||||
@RequestFilters(FormSigner.class)
|
||||
@VirtualHost
|
||||
public interface TagAsyncClient {
|
||||
/**
|
||||
* @see TagClient#createTagsInRegion(String, Iterable, Map)
|
||||
*/
|
||||
@Named("ec2:CreateTags")
|
||||
@POST
|
||||
@Path("/")
|
||||
@FormParams(keys = ACTION, values = "CreateTags")
|
||||
ListenableFuture<Void> createTagsInRegion(@EndpointParam(parser = RegionToEndpointOrProviderIfNull.class) @Nullable String region,
|
||||
@BinderParam(BindResourceIdsToIndexedFormParams.class) Iterable<String> resourceIds,
|
||||
@BinderParam(BindTagsToIndexedFormParams.class) Map<String, String> tags);
|
||||
|
||||
/**
|
||||
* @see TagClient#deleteTagsInRegion(String, Iterable, Map)
|
||||
*/
|
||||
@Named("ec2:DeleteTags")
|
||||
@POST
|
||||
@Path("/")
|
||||
@FormParams(keys = ACTION, values = "DeleteTags")
|
||||
@Fallback(VoidOnNotFoundOr404.class)
|
||||
ListenableFuture<Void> deleteTagsInRegion(@EndpointParam(parser = RegionToEndpointOrProviderIfNull.class) @Nullable String region,
|
||||
@BinderParam(BindResourceIdsToIndexedFormParams.class) Iterable<String> resourceIds,
|
||||
@BinderParam(BindTagsToIndexedFormParams.class) Map<String, String> tags);
|
||||
|
||||
/**
|
||||
* @see TagClient#describeTagsInRegion(String, Map)
|
||||
*/
|
||||
@Named("ec2:DescribeTags")
|
||||
@POST
|
||||
@Path("/")
|
||||
@FormParams(keys = ACTION, values = "DescribeTags")
|
||||
@XMLResponseParser(DescribeTagsResponseHandler.class)
|
||||
@Fallback(EmptySetOnNotFoundOr404.class)
|
||||
ListenableFuture<? extends Set<Tag>> describeTagsInRegion(@EndpointParam(parser = RegionToEndpointOrProviderIfNull.class) @Nullable String region,
|
||||
@BinderParam(BindTagFiltersToIndexedFormParams.class) Map<FilterName, Iterable<?>> filters);
|
||||
}
|
|
@ -1,86 +0,0 @@
|
|||
/**
|
||||
* Licensed to jclouds, Inc. (jclouds) under one or more
|
||||
* contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. jclouds 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.jclouds.aws.ec2.services;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import org.jclouds.aws.ec2.domain.Tag;
|
||||
import org.jclouds.aws.ec2.util.TagFilters.FilterName;
|
||||
import org.jclouds.javax.annotation.Nullable;
|
||||
|
||||
/**
|
||||
*
|
||||
* Provides Tag services for EC2. For more information, refer to the Amazon EC2
|
||||
* Developer Guide.
|
||||
*
|
||||
* <h3>Important</h3>
|
||||
* This will be removed in jclouds version 1.6
|
||||
*
|
||||
* @author grkvlt@apache.org
|
||||
* @see TagApi
|
||||
*/
|
||||
@Deprecated
|
||||
public interface TagClient {
|
||||
/**
|
||||
* Creates tags.
|
||||
*
|
||||
* @param region
|
||||
* Region to create the tag in.
|
||||
* @param resourceIds
|
||||
* IDs of the resources to tag.
|
||||
* @param tags
|
||||
* The tags to create.
|
||||
* @see #describeTagsInRegion(String, Map)
|
||||
* @see #deleteTagsInRegion(String, Iterable, Map)
|
||||
*
|
||||
* @see <a href="http://docs.amazonwebservices.com/AWSEC2/latest/APIReference/ApiReference-query-CreateTags.html" />
|
||||
*/
|
||||
void createTagsInRegion(@Nullable String region, Iterable<String> resourceIds, Map<String, String> tags);
|
||||
|
||||
/**
|
||||
* Deletes tags.
|
||||
*
|
||||
* @param region
|
||||
* Region to delete the tags from
|
||||
* @param resourceIds
|
||||
* IDs of the tagged resources.
|
||||
* @param tags
|
||||
* The tags to delete.
|
||||
*
|
||||
* @see #describeTagsInRegion(String, Map)
|
||||
* @see #createTagsInRegion(String, Iterable, Map)
|
||||
*
|
||||
* @see <a href="http://docs.amazonwebservices.com/AWSEC2/latest/APIReference/ApiReference-query-DeleteTags.html" />
|
||||
*/
|
||||
void deleteTagsInRegion(@Nullable String region, Iterable<String> resourceIds, Map<String, String> tags);
|
||||
|
||||
/**
|
||||
* Returns filtered information about tags.
|
||||
*
|
||||
* @param region
|
||||
* The bundleTask ID is tied to the Region.
|
||||
* @param filters
|
||||
* A collection of filters to apply before selecting the tags.
|
||||
*
|
||||
* @see #deleteTagsInRegion(String, Iterable, Map)
|
||||
* @see #createTagsInRegion(String, Iterable, Map)
|
||||
* @see <a href="http://docs.amazonwebservices.com/AWSEC2/latest/APIReference/ApiReference-query-DescribeTags.html" />
|
||||
*/
|
||||
Set<Tag> describeTagsInRegion(@Nullable String region, Map<FilterName, Iterable<?>> filters);
|
||||
}
|
|
@ -18,24 +18,23 @@
|
|||
*/
|
||||
package org.jclouds.aws.ec2.xml;
|
||||
|
||||
import static org.jclouds.util.SaxUtils.currentOrNull;
|
||||
import static org.jclouds.util.SaxUtils.equalsOrSuffix;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
import org.jclouds.aws.ec2.domain.AWSRunningInstance;
|
||||
import org.jclouds.date.DateCodecFactory;
|
||||
import org.jclouds.ec2.domain.Reservation;
|
||||
import org.jclouds.ec2.domain.RunningInstance;
|
||||
import org.jclouds.ec2.xml.TagSetHandler;
|
||||
import org.jclouds.location.Region;
|
||||
import org.xml.sax.Attributes;
|
||||
import org.xml.sax.SAXException;
|
||||
|
||||
import com.google.common.base.Supplier;
|
||||
import com.google.common.collect.Sets;
|
||||
import com.google.inject.Provider;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import com.google.common.collect.ImmutableSet.Builder;
|
||||
|
||||
/**
|
||||
* Parses the following XML document:
|
||||
|
@ -47,42 +46,51 @@ import com.google.inject.Provider;
|
|||
*/
|
||||
public class AWSDescribeInstancesResponseHandler extends
|
||||
BaseAWSReservationHandler<Set<Reservation<? extends RunningInstance>>> {
|
||||
private Set<Reservation<? extends RunningInstance>> reservations = Sets.newLinkedHashSet();
|
||||
private final TagSetHandler tagSetHandler;
|
||||
private Builder<Reservation<? extends RunningInstance>> reservations = ImmutableSet.<Reservation<? extends RunningInstance>>builder();
|
||||
private boolean inTagSet;
|
||||
private String key;
|
||||
private String value;
|
||||
|
||||
@Inject
|
||||
AWSDescribeInstancesResponseHandler(DateCodecFactory dateCodecFactory, @Region Supplier<String> defaultRegion,
|
||||
Provider<AWSRunningInstance.Builder> builderProvider, TagSetHandler tagSetHandler) {
|
||||
super(dateCodecFactory, defaultRegion, builderProvider);
|
||||
TagSetHandler tagSetHandler) {
|
||||
super(dateCodecFactory, defaultRegion);
|
||||
this.tagSetHandler = tagSetHandler;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void startElement(String uri, String localName, String qName, Attributes attrs) throws SAXException {
|
||||
super.startElement(uri, localName, qName, attrs);
|
||||
public void startElement(String uri, String name, String qName, Attributes attrs) throws SAXException {
|
||||
super.startElement(uri, name, qName, attrs);
|
||||
if (equalsOrSuffix(qName, "tagSet")) {
|
||||
inTagSet = true;
|
||||
}
|
||||
if (inTagSet) {
|
||||
tagSetHandler.startElement(uri, name, qName, attrs);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void characters(char ch[], int start, int length) {
|
||||
if (inTagSet) {
|
||||
tagSetHandler.characters(ch, start, length);
|
||||
} else {
|
||||
super.characters(ch, start, length);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void endElement(String uri, String name, String qName) {
|
||||
if (equalsOrSuffix(qName, "tagSet")) {
|
||||
inTagSet = false;
|
||||
builder.tags(tagSetHandler.getResult());
|
||||
} else if (inTagSet) {
|
||||
if (equalsOrSuffix(qName, "key")) {
|
||||
key = currentOrNull(currentText);
|
||||
} else if (equalsOrSuffix(qName, "value")) {
|
||||
value = currentOrNull(currentText);
|
||||
}
|
||||
tagSetHandler.endElement(uri, name, qName);
|
||||
}
|
||||
super.endElement(uri, name, qName);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<Reservation<? extends RunningInstance>> getResult() {
|
||||
return reservations;
|
||||
return reservations.build();
|
||||
}
|
||||
|
||||
protected boolean endOfReservationItem() {
|
||||
|
@ -93,10 +101,6 @@ public class AWSDescribeInstancesResponseHandler extends
|
|||
protected void inItem() {
|
||||
if (endOfReservationItem()) {
|
||||
reservations.add(super.newReservation());
|
||||
} else if (inTagSet) {
|
||||
builder.tag(key, value);
|
||||
key = null;
|
||||
value = null;
|
||||
} else {
|
||||
super.inItem();
|
||||
}
|
||||
|
|
|
@ -20,14 +20,12 @@ package org.jclouds.aws.ec2.xml;
|
|||
|
||||
import javax.inject.Inject;
|
||||
|
||||
import org.jclouds.aws.ec2.domain.AWSRunningInstance;
|
||||
import org.jclouds.date.DateCodecFactory;
|
||||
import org.jclouds.ec2.domain.Reservation;
|
||||
import org.jclouds.ec2.domain.RunningInstance;
|
||||
import org.jclouds.location.Region;
|
||||
|
||||
import com.google.common.base.Supplier;
|
||||
import com.google.inject.Provider;
|
||||
|
||||
/**
|
||||
* Parses the following XML document:
|
||||
|
@ -40,9 +38,8 @@ import com.google.inject.Provider;
|
|||
public class AWSRunInstancesResponseHandler extends BaseAWSReservationHandler<Reservation<? extends RunningInstance>> {
|
||||
|
||||
@Inject
|
||||
AWSRunInstancesResponseHandler(DateCodecFactory dateCodecFactory, @Region Supplier<String> defaultRegion,
|
||||
Provider<AWSRunningInstance.Builder> builderProvider) {
|
||||
super(dateCodecFactory, defaultRegion, builderProvider);
|
||||
AWSRunInstancesResponseHandler(DateCodecFactory dateCodecFactory, @Region Supplier<String> defaultRegion) {
|
||||
super(dateCodecFactory, defaultRegion);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -49,7 +49,6 @@ import org.xml.sax.SAXException;
|
|||
import com.google.common.base.Supplier;
|
||||
import com.google.common.collect.Maps;
|
||||
import com.google.common.collect.Sets;
|
||||
import com.google.inject.Provider;
|
||||
|
||||
/**
|
||||
*
|
||||
|
@ -62,21 +61,21 @@ public abstract class BaseAWSReservationHandler<T> extends HandlerForGeneratedRe
|
|||
|
||||
protected final DateCodec dateCodec;
|
||||
protected final Supplier<String> defaultRegion;
|
||||
protected final Provider<AWSRunningInstance.Builder> builderProvider;
|
||||
|
||||
@Inject
|
||||
public BaseAWSReservationHandler(DateCodecFactory dateCodecFactory, @Region Supplier<String> defaultRegion,
|
||||
Provider<AWSRunningInstance.Builder> builderProvider) {
|
||||
public BaseAWSReservationHandler(DateCodecFactory dateCodecFactory, @Region Supplier<String> defaultRegion) {
|
||||
this.dateCodec = dateCodecFactory.iso8601();
|
||||
this.defaultRegion = defaultRegion;
|
||||
this.builderProvider = builderProvider;
|
||||
this.builder = builderProvider.get();
|
||||
}
|
||||
|
||||
protected AWSRunningInstance.Builder builder = newBuilder();
|
||||
|
||||
protected AWSRunningInstance.Builder newBuilder() {
|
||||
return AWSRunningInstance.builder();
|
||||
}
|
||||
|
||||
protected StringBuilder currentText = new StringBuilder();
|
||||
|
||||
protected AWSRunningInstance.Builder builder;
|
||||
|
||||
protected int itemDepth;
|
||||
boolean inInstancesSet;
|
||||
// attachments
|
||||
|
@ -215,7 +214,7 @@ public abstract class BaseAWSReservationHandler<T> extends HandlerForGeneratedRe
|
|||
if (endOfInstanceItem()) {
|
||||
refineBuilderBeforeAddingInstance();
|
||||
instances.add(builder.build());
|
||||
builder = builderProvider.get();
|
||||
builder = newBuilder();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,73 +0,0 @@
|
|||
/**
|
||||
* Licensed to jclouds, Inc. (jclouds) under one or more
|
||||
* contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. jclouds 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.jclouds.aws.ec2.xml;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
import org.jclouds.aws.ec2.domain.Tag;
|
||||
import org.jclouds.http.HttpRequest;
|
||||
import org.jclouds.http.functions.ParseSax;
|
||||
import org.jclouds.http.functions.ParseSax.HandlerWithResult;
|
||||
import org.xml.sax.Attributes;
|
||||
import org.xml.sax.SAXException;
|
||||
|
||||
import com.google.common.collect.Sets;
|
||||
|
||||
/**
|
||||
* @author grkvlt@apache.org
|
||||
*/
|
||||
public class DescribeTagsResponseHandler extends ParseSax.HandlerWithResult<Set<Tag>> {
|
||||
private Set<Tag> tags = Sets.newLinkedHashSet();
|
||||
private final TagHandler tagHandler;
|
||||
|
||||
@Inject
|
||||
public DescribeTagsResponseHandler(TagHandler tagHandler) {
|
||||
this.tagHandler = tagHandler;
|
||||
}
|
||||
|
||||
public Set<Tag> getResult() {
|
||||
return tags;
|
||||
}
|
||||
|
||||
@Override
|
||||
public HandlerWithResult<Set<Tag>> setContext(HttpRequest request) {
|
||||
tagHandler.setContext(request);
|
||||
return super.setContext(request);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
|
||||
if (!qName.equals("item"))
|
||||
tagHandler.startElement(uri, localName, qName, attributes);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void endElement(String uri, String localName, String qName) throws SAXException {
|
||||
if (qName.equals("item")) {
|
||||
tags.add(tagHandler.getResult());
|
||||
}
|
||||
tagHandler.endElement(uri, localName, qName);
|
||||
}
|
||||
|
||||
public void characters(char ch[], int start, int length) {
|
||||
tagHandler.characters(ch, start, length);
|
||||
}
|
||||
}
|
|
@ -28,6 +28,7 @@ import org.jclouds.aws.ec2.domain.SpotInstanceRequest.Builder;
|
|||
import org.jclouds.aws.util.AWSUtils;
|
||||
import org.jclouds.date.DateCodec;
|
||||
import org.jclouds.date.DateCodecFactory;
|
||||
import org.jclouds.ec2.xml.TagSetHandler;
|
||||
import org.jclouds.http.functions.ParseSax;
|
||||
import org.jclouds.location.Region;
|
||||
import org.xml.sax.Attributes;
|
||||
|
|
|
@ -1,58 +0,0 @@
|
|||
/**
|
||||
* Licensed to jclouds, Inc. (jclouds) under one or more
|
||||
* contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. jclouds 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.jclouds.aws.ec2.xml;
|
||||
|
||||
import org.jclouds.aws.ec2.domain.Tag;
|
||||
import org.jclouds.aws.ec2.util.TagFilters.ResourceType;
|
||||
import org.jclouds.http.functions.ParseSax;
|
||||
import org.xml.sax.SAXException;
|
||||
|
||||
/**
|
||||
* @author grkvlt@apache.org
|
||||
*/
|
||||
public class TagHandler extends ParseSax.HandlerForGeneratedRequestWithResult<Tag> {
|
||||
private StringBuilder currentText = new StringBuilder();
|
||||
|
||||
private String resourceId;
|
||||
private ResourceType resourceType;
|
||||
private String key;
|
||||
private String value;
|
||||
|
||||
public Tag getResult() {
|
||||
Tag returnVal = new Tag(resourceId, resourceType, key, value);
|
||||
return returnVal;
|
||||
}
|
||||
|
||||
public void endElement(String uri, String name, String qName) throws SAXException {
|
||||
if (qName.equals("resourceId")) {
|
||||
this.resourceId = currentText.toString().trim();
|
||||
} else if (qName.equals("resourceType")) {
|
||||
resourceType = ResourceType.fromValue(currentText.toString().trim());
|
||||
} else if (qName.equals("key")) {
|
||||
key = currentText.toString().trim();
|
||||
} else if (qName.equals("value")) {
|
||||
value = currentText.toString().trim();
|
||||
}
|
||||
currentText = new StringBuilder();
|
||||
}
|
||||
|
||||
public void characters(char ch[], int start, int length) {
|
||||
currentText.append(ch, start, length);
|
||||
}
|
||||
}
|
|
@ -1,85 +0,0 @@
|
|||
/**
|
||||
* Licensed to jclouds, Inc. (jclouds) under one or more
|
||||
* contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. jclouds 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.jclouds.aws.ec2.xml;
|
||||
|
||||
import static org.jclouds.util.SaxUtils.currentOrNull;
|
||||
import static org.jclouds.util.SaxUtils.equalsOrSuffix;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import org.jclouds.http.functions.ParseSax;
|
||||
import org.xml.sax.Attributes;
|
||||
import org.xml.sax.SAXException;
|
||||
|
||||
import com.google.common.base.Strings;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
|
||||
/**
|
||||
* @author grkvlt@apache.org
|
||||
*/
|
||||
public class TagSetHandler extends ParseSax.HandlerForGeneratedRequestWithResult<Map<String, String>> {
|
||||
private StringBuilder currentText = new StringBuilder();
|
||||
|
||||
private ImmutableMap.Builder<String, String> result;
|
||||
private boolean inItem = false;
|
||||
private String key;
|
||||
private String value;
|
||||
|
||||
public TagSetHandler() {
|
||||
super();
|
||||
}
|
||||
|
||||
public Map<String, String> getResult() {
|
||||
return result.build();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
|
||||
if (equalsOrSuffix(qName, "tagSet")) {
|
||||
result = ImmutableMap.builder();
|
||||
} else if (qName.equals("item")) {
|
||||
inItem = true;
|
||||
key = null;
|
||||
value = null;
|
||||
}
|
||||
currentText = new StringBuilder();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void endElement(String uri, String localName, String qName) throws SAXException {
|
||||
if (qName.equals("item")) {
|
||||
inItem = false;
|
||||
if (key != null) {
|
||||
result.put(key, Strings.nullToEmpty(value));
|
||||
}
|
||||
}
|
||||
if (inItem) {
|
||||
if (qName.equals("key")) {
|
||||
key = currentOrNull(currentText);
|
||||
} else if (qName.equals("value")) {
|
||||
value = currentOrNull(currentText);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void characters(char ch[], int start, int length) {
|
||||
currentText.append(ch, start, length);
|
||||
}
|
||||
}
|
|
@ -49,7 +49,6 @@ public class AWSEC2AsyncClientTest extends BaseAWSEC2AsyncClientTest<AWSEC2Async
|
|||
assert syncClient.getSecurityGroupServices() != null;
|
||||
assert syncClient.getPlacementGroupServices() != null;
|
||||
assert syncClient.getWindowsServices() != null;
|
||||
assert syncClient.getTagServices() != null;
|
||||
|
||||
}
|
||||
|
||||
|
@ -64,7 +63,6 @@ public class AWSEC2AsyncClientTest extends BaseAWSEC2AsyncClientTest<AWSEC2Async
|
|||
assert asyncClient.getSecurityGroupServices() != null;
|
||||
assert asyncClient.getPlacementGroupServices() != null;
|
||||
assert asyncClient.getWindowsServices() != null;
|
||||
assert asyncClient.getTagServices() != null;
|
||||
}
|
||||
|
||||
@BeforeClass
|
||||
|
|
|
@ -77,13 +77,6 @@ public class AWSEC2ComputeServiceLiveTest extends EC2ComputeServiceLiveTest {
|
|||
group = "ec2";
|
||||
}
|
||||
|
||||
// aws-ec2 supports userMetadata
|
||||
@Override
|
||||
protected void checkUserMetadataContains(NodeMetadata node, ImmutableMap<String, String> userMetadata) {
|
||||
assert node.getUserMetadata().equals(userMetadata) : String.format("node userMetadata did not match %s %s",
|
||||
userMetadata, node);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Test
|
||||
public void testExtendedOptionsAndLogin() throws Exception {
|
||||
|
@ -103,12 +96,14 @@ public class AWSEC2ComputeServiceLiveTest extends EC2ComputeServiceLiveTest {
|
|||
Date before = new Date();
|
||||
|
||||
ImmutableMap<String, String> userMetadata = ImmutableMap.<String, String> of("test", group);
|
||||
|
||||
ImmutableSet<String> tags = ImmutableSet.of(group);
|
||||
|
||||
// note that if you change the location, you must also specify image parameters
|
||||
Template template = client.templateBuilder().locationId(region).osFamily(AMZN_LINUX).os64Bit(true).build();
|
||||
template.getOptions().tags(tags);
|
||||
template.getOptions().userMetadata(userMetadata);
|
||||
template.getOptions().tags(tags);
|
||||
template.getOptions().as(AWSEC2TemplateOptions.class).enableMonitoring();
|
||||
template.getOptions().as(AWSEC2TemplateOptions.class).spotPrice(0.3f);
|
||||
|
||||
|
@ -137,9 +132,6 @@ public class AWSEC2ComputeServiceLiveTest extends EC2ComputeServiceLiveTest {
|
|||
Set<? extends NodeMetadata> nodes = client.createNodesInGroup(group, 1, template);
|
||||
NodeMetadata first = getOnlyElement(nodes);
|
||||
|
||||
// Name metadata should turn into node.name
|
||||
assertEquals(first.getName(), group);
|
||||
|
||||
checkUserMetadataContains(first, userMetadata);
|
||||
checkTagsInNodeEquals(first, tags);
|
||||
|
||||
|
|
|
@ -1,168 +0,0 @@
|
|||
/**
|
||||
* Licensed to jclouds, Inc. (jclouds) under one or more
|
||||
* contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. jclouds 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.jclouds.aws.ec2.compute;
|
||||
|
||||
import static org.testng.Assert.assertEquals;
|
||||
import static org.testng.Assert.assertNotNull;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
import org.jclouds.aws.ec2.AWSEC2ApiMetadata;
|
||||
import org.jclouds.aws.ec2.AWSEC2Client;
|
||||
import org.jclouds.aws.ec2.domain.AWSRunningInstance;
|
||||
import org.jclouds.aws.ec2.services.AWSSecurityGroupClient;
|
||||
import org.jclouds.compute.domain.NodeMetadata;
|
||||
import org.jclouds.compute.domain.Template;
|
||||
import org.jclouds.compute.internal.BaseComputeServiceContextLiveTest;
|
||||
import org.jclouds.compute.predicates.NodePredicates;
|
||||
import org.jclouds.ec2.EC2Client;
|
||||
import org.jclouds.ec2.compute.EC2ComputeServiceLiveTest;
|
||||
import org.jclouds.ec2.domain.KeyPair;
|
||||
import org.jclouds.ec2.domain.SecurityGroup;
|
||||
import org.jclouds.ec2.services.InstanceClient;
|
||||
import org.jclouds.ec2.services.KeyPairClient;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
import com.google.common.base.Function;
|
||||
import com.google.common.base.Stopwatch;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import com.google.common.collect.Iterables;
|
||||
|
||||
/**
|
||||
*
|
||||
* Disabled, as it doesn't pass
|
||||
*
|
||||
* @author Aled Sage
|
||||
*/
|
||||
@Test(enabled = false, groups = "live", singleThreaded = true, testName = "IncidentalResourcesGetCleanedUpLiveTest")
|
||||
public class IncidentalResourcesGetCleanedUpLiveTest extends BaseComputeServiceContextLiveTest {
|
||||
|
||||
public IncidentalResourcesGetCleanedUpLiveTest() {
|
||||
provider = "aws-ec2";
|
||||
}
|
||||
|
||||
@Test(enabled = false)
|
||||
public void testIncidentalResourcesGetCleanedUpOnlyOnLastInstanceDestroyNode() throws Exception {
|
||||
Function<String,Void> destroyer = new Function<String,Void>() {
|
||||
@Override
|
||||
public Void apply(String instanceId) {
|
||||
view.getComputeService().destroyNode(instanceId);
|
||||
return null;
|
||||
}
|
||||
};
|
||||
runIncidentalResourcesGetCleanedUpOnlyOnLastInstanceDestroy(destroyer);
|
||||
}
|
||||
|
||||
@Test(enabled = false)
|
||||
public void testIncidentalResourcesGetCleanedUpOnlyOnLastInstanceDestroyNodesMatching() throws Exception {
|
||||
Function<String,Void> destroyer = new Function<String,Void>() {
|
||||
@Override
|
||||
public Void apply(String instanceId) {
|
||||
view.getComputeService().destroyNodesMatching(NodePredicates.<NodeMetadata>withIds(instanceId));
|
||||
return null;
|
||||
}
|
||||
};
|
||||
runIncidentalResourcesGetCleanedUpOnlyOnLastInstanceDestroy(destroyer);
|
||||
}
|
||||
|
||||
private void runIncidentalResourcesGetCleanedUpOnlyOnLastInstanceDestroy(Function<String,Void> destroyer) throws Exception {
|
||||
AWSSecurityGroupClient securityGroupClient = AWSEC2Client.class.cast(view.unwrap(AWSEC2ApiMetadata.CONTEXT_TOKEN).getApi())
|
||||
.getSecurityGroupServices();
|
||||
|
||||
KeyPairClient keyPairClient = EC2Client.class.cast(view.unwrap(AWSEC2ApiMetadata.CONTEXT_TOKEN).getApi())
|
||||
.getKeyPairServices();
|
||||
|
||||
InstanceClient instanceClient = EC2Client.class.cast(view.unwrap(AWSEC2ApiMetadata.CONTEXT_TOKEN).getApi())
|
||||
.getInstanceServices();
|
||||
|
||||
String group = "aws-ec2-incidental";
|
||||
String region = null;
|
||||
|
||||
try {
|
||||
// Create two instances
|
||||
// TODO set spotPrice(0.3f) ?
|
||||
Template template = view.getComputeService().templateBuilder().build();
|
||||
Set<? extends NodeMetadata> nodes = view.getComputeService().createNodesInGroup(group, 2, template);
|
||||
NodeMetadata first = Iterables.get(nodes, 0);
|
||||
NodeMetadata second = Iterables.get(nodes, 1);
|
||||
|
||||
String instanceId1 = Iterables.get(nodes, 0).getProviderId();
|
||||
String instanceId2 = Iterables.get(nodes, 1).getProviderId();
|
||||
|
||||
AWSRunningInstance instance1 = AWSRunningInstance.class.cast(EC2ComputeServiceLiveTest.getInstance(instanceClient, instanceId1));
|
||||
AWSRunningInstance instance2 = AWSRunningInstance.class.cast(EC2ComputeServiceLiveTest.getInstance(instanceClient, instanceId2));
|
||||
|
||||
// Assert the two instances are in the same groups
|
||||
region = instance1.getRegion();
|
||||
String expectedSecurityGroupName = "jclouds#" + group;
|
||||
|
||||
assertEquals(instance1.getRegion(), region);
|
||||
assertNotNull(instance1.getKeyName());
|
||||
assertEquals(instance1.getRegion(), instance2.getRegion(), "Nodes are not in the same region");
|
||||
assertEquals(instance1.getKeyName(), instance2.getKeyName(), "Nodes do not have same key-pair name");
|
||||
assertEquals(instance1.getGroupNames(), instance2.getGroupNames(), "Nodes are not in the same group");
|
||||
assertEquals(instance1.getGroupNames(), ImmutableSet.of(expectedSecurityGroupName), "Nodes are not in the expected security group");
|
||||
|
||||
// Assert a single key-pair and security group has been created
|
||||
String expectedKeyPairName = instance1.getKeyName();
|
||||
Set<SecurityGroup> securityGroups = securityGroupClient.describeSecurityGroupsInRegion(region, expectedSecurityGroupName);
|
||||
Set<KeyPair> keyPairs = keyPairClient.describeKeyPairsInRegion(region, expectedKeyPairName);
|
||||
assertEquals(securityGroups.size(), 1);
|
||||
assertEquals(Iterables.get(securityGroups, 0).getName(), expectedSecurityGroupName);
|
||||
assertEquals(keyPairs.size(), 1);
|
||||
assertEquals(Iterables.get(keyPairs, 0).getKeyName(), expectedKeyPairName);
|
||||
|
||||
// Destroy the first node; the key-pair and security-group should still remain
|
||||
destroyer.apply(first.getId());
|
||||
|
||||
Set<SecurityGroup> securityGroupsAfterDestroyFirst = securityGroupClient.describeSecurityGroupsInRegion(region, expectedSecurityGroupName);
|
||||
Set<KeyPair> keyPairsAfterDestroyFirst = keyPairClient.describeKeyPairsInRegion(region, expectedKeyPairName);
|
||||
assertEquals(securityGroupsAfterDestroyFirst, securityGroups);
|
||||
assertEquals(keyPairsAfterDestroyFirst, keyPairs);
|
||||
|
||||
// Destroy the second node; the key-pair and security-group should be automatically deleted
|
||||
// It can take some time after destroyNode returns for the securityGroup and keyPair to be completely removed.
|
||||
// Therefore try repeatedly.
|
||||
destroyer.apply(second.getId());
|
||||
|
||||
final int TIMEOUT_MS = 30*1000;
|
||||
boolean firstAttempt = true;
|
||||
boolean done;
|
||||
Set<SecurityGroup> securityGroupsAfterDestroyAll;
|
||||
Set<KeyPair> keyPairsAfterDestroyAll;
|
||||
Stopwatch stopwatch = new Stopwatch();
|
||||
stopwatch.start();
|
||||
do {
|
||||
if (!firstAttempt) Thread.sleep(1000);
|
||||
firstAttempt = false;
|
||||
securityGroupsAfterDestroyAll = securityGroupClient.describeSecurityGroupsInRegion(region, expectedSecurityGroupName);
|
||||
keyPairsAfterDestroyAll = keyPairClient.describeKeyPairsInRegion(region, expectedKeyPairName);
|
||||
done = securityGroupsAfterDestroyAll.isEmpty() && keyPairsAfterDestroyAll.isEmpty();
|
||||
} while (!done && stopwatch.elapsedMillis() < TIMEOUT_MS);
|
||||
|
||||
assertEquals(securityGroupsAfterDestroyAll, ImmutableSet.of());
|
||||
assertEquals(keyPairsAfterDestroyAll, ImmutableSet.of());
|
||||
|
||||
} finally {
|
||||
view.getComputeService().destroyNodesMatching(NodePredicates.inGroup(group));
|
||||
|
||||
if (region != null) EC2ComputeServiceLiveTest.cleanupExtendedStuffInRegion(region, securityGroupClient, keyPairClient, group);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,101 @@
|
|||
/**
|
||||
* Licensed to jclouds, Inc. (jclouds) under one or more
|
||||
* contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. jclouds 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.jclouds.aws.ec2.compute.functions;
|
||||
|
||||
import static org.easymock.EasyMock.createMock;
|
||||
import static org.easymock.EasyMock.expect;
|
||||
import static org.easymock.EasyMock.replay;
|
||||
import static org.easymock.EasyMock.verify;
|
||||
import static org.testng.Assert.assertEquals;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
import org.jclouds.aws.ec2.AWSEC2Client;
|
||||
import org.jclouds.aws.ec2.domain.AWSRunningInstance;
|
||||
import org.jclouds.aws.ec2.domain.SpotInstanceRequest;
|
||||
import org.jclouds.aws.ec2.services.AWSInstanceClient;
|
||||
import org.jclouds.aws.ec2.services.SpotInstanceClient;
|
||||
import org.jclouds.ec2.compute.domain.RegionAndName;
|
||||
import org.jclouds.ec2.domain.Reservation;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
import com.google.common.base.Function;
|
||||
import com.google.common.base.Functions;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
|
||||
/**
|
||||
* @author Adrian Cole
|
||||
*/
|
||||
@Test(groups = "unit")
|
||||
public class PresentSpotRequestsAndInstancesTest {
|
||||
AWSRunningInstance instance1 = createMock(AWSRunningInstance.class);
|
||||
AWSRunningInstance instance2 = createMock(AWSRunningInstance.class);
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Test
|
||||
public void testWhenInstancesPresentSingleCall() {
|
||||
|
||||
AWSEC2Client client = createMock(AWSEC2Client.class);
|
||||
AWSInstanceClient instanceClient = createMock(AWSInstanceClient.class);
|
||||
Function<SpotInstanceRequest, AWSRunningInstance> converter = createMock(Function.class);
|
||||
|
||||
expect(client.getInstanceServices()).andReturn(instanceClient);
|
||||
|
||||
// avoid imatcher fail. if you change this, be sure to check multiple jres
|
||||
expect(instanceClient.describeInstancesInRegion("us-east-1", "i-aaaa", "i-bbbb")).andReturn(
|
||||
Set.class.cast(ImmutableSet.of(Reservation.<AWSRunningInstance> builder().region("us-east-1")
|
||||
.instances(ImmutableSet.of(instance1, instance2)).build())));
|
||||
|
||||
replay(client, instanceClient, converter);
|
||||
|
||||
PresentSpotRequestsAndInstances fn = new PresentSpotRequestsAndInstances(client, converter);
|
||||
|
||||
assertEquals(fn.apply(ImmutableSet.of(new RegionAndName("us-east-1", "i-aaaa"), new RegionAndName("us-east-1",
|
||||
"i-bbbb"))), ImmutableSet.of(instance1, instance2));
|
||||
|
||||
verify(client, instanceClient, converter);
|
||||
}
|
||||
|
||||
SpotInstanceRequest spot1 = createMock(SpotInstanceRequest.class);
|
||||
SpotInstanceRequest spot2 = createMock(SpotInstanceRequest.class);
|
||||
|
||||
@Test
|
||||
public void testWhenSpotsPresentSingleCall() {
|
||||
|
||||
Function<SpotInstanceRequest, AWSRunningInstance> converter = Functions.forMap(ImmutableMap.of(spot1, instance1,
|
||||
spot2, instance2));
|
||||
|
||||
AWSEC2Client client = createMock(AWSEC2Client.class);
|
||||
SpotInstanceClient spotClient = createMock(SpotInstanceClient.class);
|
||||
|
||||
expect(client.getSpotInstanceServices()).andReturn(spotClient);
|
||||
expect(spotClient.describeSpotInstanceRequestsInRegion("us-east-1", "sir-aaaa", "sir-bbbb")).andReturn(
|
||||
ImmutableSet.of(spot1, spot2));
|
||||
|
||||
replay(client, spotClient);
|
||||
|
||||
PresentSpotRequestsAndInstances fn = new PresentSpotRequestsAndInstances(client, converter);
|
||||
|
||||
assertEquals(fn.apply(ImmutableSet.of(new RegionAndName("us-east-1", "sir-aaaa"), new RegionAndName("us-east-1",
|
||||
"sir-bbbb"))), ImmutableSet.of(instance1, instance2));
|
||||
|
||||
verify(client, spotClient);
|
||||
}
|
||||
}
|
|
@ -1,108 +0,0 @@
|
|||
/**
|
||||
* Licensed to jclouds, Inc. (jclouds) under one or more
|
||||
* contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. jclouds 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.jclouds.aws.ec2.services;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.Map;
|
||||
|
||||
import org.jclouds.Fallbacks.EmptySetOnNotFoundOr404;
|
||||
import org.jclouds.Fallbacks.VoidOnNotFoundOr404;
|
||||
import org.jclouds.aws.ec2.util.TagFilters;
|
||||
import org.jclouds.aws.ec2.xml.DescribeTagsResponseHandler;
|
||||
import org.jclouds.http.HttpRequest;
|
||||
import org.jclouds.http.functions.ParseSax;
|
||||
import org.jclouds.http.functions.ReleasePayloadAndReturn;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
|
||||
/**
|
||||
* Tests behavior of {@code TagsAsyncClient}
|
||||
*
|
||||
* @author grkvlt@apache.org
|
||||
*/
|
||||
// NOTE:without testName, this will not call @Before* and fail w/NPE during surefire
|
||||
@Test(groups = "unit", testName = "TagsAsyncClientTest")
|
||||
public class TagAsyncClientTest extends BaseAWSEC2AsyncClientTest<TagAsyncClient> {
|
||||
public void testDeleteTags() throws SecurityException, NoSuchMethodException, IOException {
|
||||
Method method = TagAsyncClient.class.getMethod("deleteTagsInRegion", String.class, Iterable.class, Map.class);
|
||||
HttpRequest request = processor.createRequest(method, null, ImmutableList.<String>builder().add("xxx").build(), ImmutableMap.<String, String>builder().put("yyy", "zzz").build());
|
||||
|
||||
assertRequestLineEquals(request, "POST https://ec2.us-east-1.amazonaws.com/ HTTP/1.1");
|
||||
assertNonPayloadHeadersEqual(request, "Host: ec2.us-east-1.amazonaws.com\n");
|
||||
assertPayloadEquals(request, "Action=DeleteTags&Tag.1.Key=yyy&Tag.1.Value=zzz&ResourceId.1=xxx",
|
||||
"application/x-www-form-urlencoded", false);
|
||||
|
||||
assertResponseParserClassEquals(method, request, ReleasePayloadAndReturn.class);
|
||||
assertSaxResponseParserClassEquals(method, null);
|
||||
assertFallbackClassEquals(method, VoidOnNotFoundOr404.class);
|
||||
|
||||
checkFilters(request);
|
||||
}
|
||||
|
||||
public void testCreateTags() throws SecurityException, NoSuchMethodException, IOException {
|
||||
Method method = TagAsyncClient.class.getMethod("createTagsInRegion", String.class, Iterable.class, Map.class);
|
||||
HttpRequest request = processor.createRequest(method, null, ImmutableList.<String>builder().add("xxx").build(), ImmutableMap.<String, String>builder().put("yyy", "zzz").build());
|
||||
|
||||
assertRequestLineEquals(request, "POST https://ec2.us-east-1.amazonaws.com/ HTTP/1.1");
|
||||
assertNonPayloadHeadersEqual(request, "Host: ec2.us-east-1.amazonaws.com\n");
|
||||
assertPayloadEquals(request, "Action=CreateTags&Tag.1.Key=yyy&Tag.1.Value=zzz&ResourceId.1=xxx",
|
||||
"application/x-www-form-urlencoded", false);
|
||||
|
||||
assertResponseParserClassEquals(method, request, ReleasePayloadAndReturn.class);
|
||||
assertSaxResponseParserClassEquals(method, null);
|
||||
assertFallbackClassEquals(method, null);
|
||||
|
||||
checkFilters(request);
|
||||
}
|
||||
|
||||
public void testDescribeTags() throws SecurityException, NoSuchMethodException, IOException {
|
||||
Method method = TagAsyncClient.class.getMethod("describeTagsInRegion", String.class, Map.class);
|
||||
HttpRequest request = processor.createRequest(method, null, TagFilters.filters().build());
|
||||
|
||||
assertRequestLineEquals(request, "POST https://ec2.us-east-1.amazonaws.com/ HTTP/1.1");
|
||||
assertNonPayloadHeadersEqual(request, "Host: ec2.us-east-1.amazonaws.com\n");
|
||||
assertPayloadEquals(request, "Action=DescribeTags",
|
||||
"application/x-www-form-urlencoded", false);
|
||||
|
||||
assertResponseParserClassEquals(method, request, ParseSax.class);
|
||||
assertSaxResponseParserClassEquals(method, DescribeTagsResponseHandler.class);
|
||||
assertFallbackClassEquals(method, EmptySetOnNotFoundOr404.class);
|
||||
|
||||
checkFilters(request);
|
||||
}
|
||||
|
||||
public void testDescribeTagsArgs() throws SecurityException, NoSuchMethodException, IOException {
|
||||
Method method = TagAsyncClient.class.getMethod("describeTagsInRegion", String.class, Map.class);
|
||||
HttpRequest request = processor.createRequest(method, null, TagFilters.filters().key("one").key("two").build());
|
||||
|
||||
assertRequestLineEquals(request, "POST https://ec2.us-east-1.amazonaws.com/ HTTP/1.1");
|
||||
assertNonPayloadHeadersEqual(request, "Host: ec2.us-east-1.amazonaws.com\n");
|
||||
assertPayloadEquals(request, "Action=DescribeTags&Filter.1.Name=key&Filter.1.Value.1=one&Filter.1.Value.2=two",
|
||||
"application/x-www-form-urlencoded", false);
|
||||
|
||||
assertResponseParserClassEquals(method, request, ParseSax.class);
|
||||
assertSaxResponseParserClassEquals(method, DescribeTagsResponseHandler.class);
|
||||
assertFallbackClassEquals(method, EmptySetOnNotFoundOr404.class);
|
||||
|
||||
checkFilters(request);
|
||||
}
|
||||
}
|
|
@ -1,118 +0,0 @@
|
|||
/**
|
||||
* Licensed to jclouds, Inc. (jclouds) under one or more
|
||||
* contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. jclouds 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.jclouds.aws.ec2.services;
|
||||
|
||||
import static com.google.common.collect.Iterables.getOnlyElement;
|
||||
import static org.testng.Assert.assertEquals;
|
||||
import static org.testng.Assert.assertNotNull;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
import org.jclouds.aws.ec2.AWSEC2ApiMetadata;
|
||||
import org.jclouds.aws.ec2.domain.AWSRunningInstance;
|
||||
import org.jclouds.aws.ec2.domain.Tag;
|
||||
import org.jclouds.aws.ec2.util.TagFilters;
|
||||
import org.jclouds.aws.ec2.util.TagFilters.ResourceType;
|
||||
import org.jclouds.compute.internal.BaseComputeServiceContextLiveTest;
|
||||
import org.testng.annotations.AfterClass;
|
||||
import org.testng.annotations.BeforeClass;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import com.google.common.collect.Iterables;
|
||||
|
||||
/**
|
||||
* Tests live behavior of {@code TagClient}
|
||||
*
|
||||
* @author grkvlt@apache.org
|
||||
*/
|
||||
@Test(groups = "live", singleThreaded = true)
|
||||
public class TagClientLiveTest extends BaseComputeServiceContextLiveTest {
|
||||
public TagClientLiveTest() {
|
||||
provider = "aws-ec2";
|
||||
}
|
||||
|
||||
private TagClient client;
|
||||
protected String testGroup;
|
||||
|
||||
@Override
|
||||
@BeforeClass(groups = { "integration", "live" })
|
||||
public void setupContext() {
|
||||
super.setupContext();
|
||||
client = view.unwrap(AWSEC2ApiMetadata.CONTEXT_TOKEN).getApi().getTagServices();
|
||||
|
||||
try {
|
||||
testGroup = view.unwrap(AWSEC2ApiMetadata.CONTEXT_TOKEN).getApi().getSecurityGroupServices().createSecurityGroupInRegionAndReturnId(null,
|
||||
"test-group", "test-group");
|
||||
} catch (IllegalStateException e) {
|
||||
// already exists
|
||||
testGroup = Iterables.get(
|
||||
view.unwrap(AWSEC2ApiMetadata.CONTEXT_TOKEN).getApi().getSecurityGroupServices().describeSecurityGroupsInRegion(null, "test-group"), 0)
|
||||
.getId();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@AfterClass(groups = { "integration", "live" })
|
||||
protected void tearDownContext() {
|
||||
view.unwrap(AWSEC2ApiMetadata.CONTEXT_TOKEN).getApi().getSecurityGroupServices().deleteSecurityGroupInRegionById(null, testGroup);
|
||||
super.tearDownContext();
|
||||
}
|
||||
|
||||
public static final String PREFIX = System.getProperty("user.name") + "-ec2";
|
||||
|
||||
@Test
|
||||
void test() {
|
||||
cleanupTag(testGroup, "test-key");
|
||||
cleanupTag(testGroup, "empty-key");
|
||||
try {
|
||||
client.createTagsInRegion(null, ImmutableList.<String>builder().add(testGroup).build(), ImmutableMap.<String, String>builder().put("test-key", "test-value").build());
|
||||
checkTag(testGroup, ResourceType.SECURITY_GROUP, "test-key", "test-value");
|
||||
client.createTagsInRegion(null, ImmutableList.<String>builder().add(testGroup).build(), ImmutableMap.<String, String>builder().put("empty-key", "").build());
|
||||
checkTag(testGroup, ResourceType.SECURITY_GROUP, "empty-key", "");
|
||||
} finally {
|
||||
cleanupTag(testGroup, "test-key");
|
||||
cleanupTag(testGroup, "empty-key");
|
||||
}
|
||||
}
|
||||
|
||||
protected void cleanupTag(String resourceId, String key) {
|
||||
try {
|
||||
client.deleteTagsInRegion(null, ImmutableList.<String>builder().add(resourceId).build(), ImmutableMap.<String, String>builder().put(key, null).build());
|
||||
} catch (Exception e) {
|
||||
// Ignore
|
||||
}
|
||||
}
|
||||
|
||||
protected void checkTag(String resourceId, ResourceType resourceType, String key, String value) {
|
||||
Set<Tag> results = client.describeTagsInRegion(null, TagFilters.filters().resourceId(resourceId).resourceType(resourceType).keyValuePair(key, value).build());
|
||||
assertNotNull(results);
|
||||
assertEquals(results.size(), 1);
|
||||
Tag tag = Iterables.getOnlyElement(results);
|
||||
assertEquals(tag.getResourceId(), resourceId);
|
||||
assertEquals(tag.getResourceType(), resourceType);
|
||||
assertEquals(tag.getKey(), key);
|
||||
assertEquals(tag.getValue(), value);
|
||||
}
|
||||
|
||||
protected AWSRunningInstance getInstance(AWSInstanceClient instanceClient, String id) {
|
||||
return getOnlyElement(getOnlyElement(instanceClient.describeInstancesInRegion(null, id)));
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue