Issue 713:support userMetadata in createNodesInGroup in byon, cloudservers, and aws-ec2

This commit is contained in:
Adrian Cole 2011-10-07 00:34:44 -07:00
parent 031ee4bee5
commit 842da34982
53 changed files with 1104 additions and 614 deletions

View File

@ -20,10 +20,13 @@ package org.jclouds.byon;
import java.net.URI; import java.net.URI;
import java.util.HashSet; import java.util.HashSet;
import java.util.Map;
import java.util.Set; import java.util.Set;
import com.google.common.base.Objects; import com.google.common.base.Objects;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet; import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Maps;
/** /**
* *
@ -48,6 +51,7 @@ public class Node {
private int loginPort = 22; private int loginPort = 22;
private String group; private String group;
private Set<String> tags = ImmutableSet.of(); private Set<String> tags = ImmutableSet.of();
private Map<String, String> metadata = ImmutableMap.<String, String>of();
private String username; private String username;
private String credential; private String credential;
private URI credentialUrl; private URI credentialUrl;
@ -118,6 +122,11 @@ public class Node {
return this; return this;
} }
public Builder metadata(Map<String, String> metadata) {
this.metadata = ImmutableMap.copyOf(metadata);
return this;
}
public Builder username(String username) { public Builder username(String username) {
this.username = username; this.username = username;
return this; return this;
@ -140,13 +149,14 @@ public class Node {
public Node build() { public Node build() {
return new Node(id, name, description, hostname, locationId, osArch, osFamily, osDescription, osVersion, return new Node(id, name, description, hostname, locationId, osArch, osFamily, osDescription, osVersion,
os64Bit, loginPort, group, tags, username, credential, credentialUrl, sudoPassword); os64Bit, loginPort, group, tags, metadata, username, credential, credentialUrl, sudoPassword);
} }
} }
public Node(String id, String name, String description, String hostname, String locationId, String osArch, public Node(String id, String name, String description, String hostname, String locationId, String osArch,
String osFamily, String osDescription, String osVersion, boolean os64Bit, int loginPort, String group, String osFamily, String osDescription, String osVersion, boolean os64Bit, int loginPort, String group,
Iterable<String> tags, String username, String credential, URI credentialUrl, String sudoPassword) { Iterable<String> tags, Map<String, String> metadata, String username, String credential, URI credentialUrl,
String sudoPassword) {
this.id = id; this.id = id;
this.name = name; this.name = name;
this.description = description; this.description = description;
@ -160,6 +170,7 @@ public class Node {
this.loginPort = loginPort; this.loginPort = loginPort;
this.group = group; this.group = group;
this.tags = ImmutableSet.copyOf(tags); this.tags = ImmutableSet.copyOf(tags);
this.metadata = ImmutableMap.copyOf(metadata);
this.username = username; this.username = username;
this.credential = credential; this.credential = credential;
this.credentialUrl = credentialUrl; this.credentialUrl = credentialUrl;
@ -179,6 +190,7 @@ public class Node {
private final boolean os64Bit; private final boolean os64Bit;
private final String group; private final String group;
private final Set<String> tags; private final Set<String> tags;
private final Map<String, String> metadata;
private final String username; private final String username;
private final String credential; private final String credential;
private final URI credentialUrl; private final URI credentialUrl;
@ -239,6 +251,10 @@ public class Node {
return tagSet; return tagSet;
} }
public Map<String, String> getMetadata() {
return Maps.newLinkedHashMap(this.metadata);
}
public String getUsername() { public String getUsername() {
return username; return username;
} }
@ -269,12 +285,12 @@ public class Node {
@Override @Override
public String toString() { public String toString() {
return Objects.toStringHelper(this).add("id", id).add("name", name).add("description", description).add( return Objects.toStringHelper(this).add("id", id).add("name", name).add("description", description)
"locationId", locationId).add("hostname", hostname).add("osArch", osArch).add("osFamily", osFamily).add( .add("locationId", locationId).add("hostname", hostname).add("osArch", osArch).add("osFamily", osFamily)
"osDescription", osDescription).add("osVersion", osVersion).add("os64Bit", os64Bit).add("group", group) .add("osDescription", osDescription).add("osVersion", osVersion).add("os64Bit", os64Bit)
.add("loginPort", loginPort).add("tags", tags).add("username", username).add("hasCredential", .add("group", group).add("loginPort", loginPort).add("tags", tags).add("metadata", metadata)
credential != null || credentialUrl != null).add("hasSudoPassword", sudoPassword != null) .add("username", username).add("hasCredential", credential != null || credentialUrl != null)
.toString(); .add("hasSudoPassword", sudoPassword != null).toString();
} }
} }

View File

@ -21,6 +21,7 @@ package org.jclouds.byon.domain;
import java.io.InputStream; import java.io.InputStream;
import java.net.URI; import java.net.URI;
import java.util.List; import java.util.List;
import java.util.Map;
import org.jclouds.byon.Node; import org.jclouds.byon.Node;
import org.jclouds.util.Strings2; import org.jclouds.util.Strings2;
@ -34,6 +35,7 @@ import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableMap.Builder; import com.google.common.collect.ImmutableMap.Builder;
import com.google.common.collect.Lists; import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.io.Closeables; import com.google.common.io.Closeables;
/** /**
@ -54,6 +56,8 @@ import com.google.common.io.Closeables;
* group: hadoop * group: hadoop
* tags: * tags:
* - vanilla * - vanilla
* metadata:
* key1: val1
* username: kelvin * username: kelvin
* credential: password_or_rsa * credential: password_or_rsa
* or * or
@ -78,6 +82,7 @@ public class YamlNode {
public boolean os_64bit; public boolean os_64bit;
public String group; public String group;
public List<String> tags = Lists.newArrayList(); public List<String> tags = Lists.newArrayList();
public Map<String, String> metadata = Maps.newLinkedHashMap();
public String username; public String username;
public String credential; public String credential;
public String credential_url; public String credential_url;
@ -91,7 +96,7 @@ public class YamlNode {
return Node.builder().id(arg0.id).name(arg0.name).description(arg0.description).locationId(arg0.location_id) return Node.builder().id(arg0.id).name(arg0.name).description(arg0.description).locationId(arg0.location_id)
.hostname(arg0.hostname).osArch(arg0.os_arch).osFamily(arg0.os_family).osDescription( .hostname(arg0.hostname).osArch(arg0.os_arch).osFamily(arg0.os_family).osDescription(
arg0.os_description).osVersion(arg0.os_version).os64Bit(arg0.os_64bit).group(arg0.group) arg0.os_description).osVersion(arg0.os_version).os64Bit(arg0.os_64bit).group(arg0.group)
.loginPort(arg0.login_port).tags(arg0.tags).username(arg0.username).credential(arg0.credential).credentialUrl( .loginPort(arg0.login_port).tags(arg0.tags).metadata(arg0.metadata).username(arg0.username).credential(arg0.credential).credentialUrl(
arg0.credential_url != null ? URI.create(arg0.credential_url) : null).sudoPassword( arg0.credential_url != null ? URI.create(arg0.credential_url) : null).sudoPassword(
arg0.sudo_password).build(); arg0.sudo_password).build();
} }
@ -152,6 +157,8 @@ public class YamlNode {
prettier.put("group", in.group); prettier.put("group", in.group);
if (in.tags.size() != 0) if (in.tags.size() != 0)
prettier.put("tags", in.tags); prettier.put("tags", in.tags);
if (in.metadata.size() != 0)
prettier.put("metadata", in.metadata);
if (in.username != null) if (in.username != null)
prettier.put("username", in.username); prettier.put("username", in.username);
if (in.credential != null) if (in.credential != null)
@ -193,6 +200,7 @@ public class YamlNode {
yaml.login_port = arg0.getLoginPort(); yaml.login_port = arg0.getLoginPort();
yaml.group = arg0.getGroup(); yaml.group = arg0.getGroup();
yaml.tags = ImmutableList.copyOf(arg0.getTags()); yaml.tags = ImmutableList.copyOf(arg0.getTags());
yaml.metadata = ImmutableMap.copyOf(arg0.getMetadata());
yaml.username = arg0.getUsername(); yaml.username = arg0.getUsername();
yaml.credential = arg0.getCredential(); yaml.credential = arg0.getCredential();
yaml.credential_url = arg0.getCredentialUrl() != null ? arg0.getCredentialUrl().toASCIIString() : null; yaml.credential_url = arg0.getCredentialUrl() != null ? arg0.getCredentialUrl().toASCIIString() : null;

View File

@ -84,6 +84,7 @@ public class NodeToNodeMetadata implements Function<Node, NodeMetadata> {
builder.location(findLocationWithId(from.getLocationId())); builder.location(findLocationWithId(from.getLocationId()));
builder.group(from.getGroup()); builder.group(from.getGroup());
builder.tags(from.getTags()); builder.tags(from.getTags());
builder.userMetadata(from.getMetadata());
builder.operatingSystem(OperatingSystem.builder().arch(from.getOsArch()).family( builder.operatingSystem(OperatingSystem.builder().arch(from.getOsArch()).family(
OsFamily.fromValue(from.getOsFamily())).description(from.getOsDescription()) OsFamily.fromValue(from.getOsFamily())).description(from.getOsDescription())
.version(from.getOsVersion()).build()); .version(from.getOsVersion()).build());

View File

@ -85,6 +85,7 @@ public class NodeToNodeMetadataTest {
.loginPort(loginPort) .loginPort(loginPort)
.hostname("cluster-" + id + ".mydomain.com") .hostname("cluster-" + id + ".mydomain.com")
.location(location) .location(location)
.userMetadata(ImmutableMap.of("Name", "foo"))
.state(NodeState.RUNNING) .state(NodeState.RUNNING)
.operatingSystem( .operatingSystem(
OperatingSystem.builder().description("redhat").family(OsFamily.RHEL).arch("x86").version("5.3") OperatingSystem.builder().description("redhat").family(OsFamily.RHEL).arch("x86").version("5.3")

View File

@ -34,23 +34,23 @@ import com.google.common.collect.ImmutableMap;
* @author Adrian Cole * @author Adrian Cole
*/ */
public class NodesFromYamlTest { public class NodesFromYamlTest {
public static final String key = new StringBuilder().append("-----BEGIN RSA PRIVATE KEY-----\n").append( public static final String key = new StringBuilder().append("-----BEGIN RSA PRIVATE KEY-----\n")
"MIIEowIBAAKCAQEAuzaE6azgUxwESX1rCGdJ5xpdrc1XC311bOGZBCE8NA+CpFh2\n").append( .append("MIIEowIBAAKCAQEAuzaE6azgUxwESX1rCGdJ5xpdrc1XC311bOGZBCE8NA+CpFh2\n")
"u01Vfv68NC4u6LFgdXSY1vQt6hiA5TNqQk0TyVfFAunbXgTekF6XqDPQUf1nq9aZ\n").append( .append("u01Vfv68NC4u6LFgdXSY1vQt6hiA5TNqQk0TyVfFAunbXgTekF6XqDPQUf1nq9aZ\n")
"lMvo4vlaLDKBkhG5HJE/pIa0iB+RMZLS0GhxsIWerEDmYdHKM25o\n").append("-----END RSA PRIVATE KEY-----\n") .append("lMvo4vlaLDKBkhG5HJE/pIa0iB+RMZLS0GhxsIWerEDmYdHKM25o\n").append("-----END RSA PRIVATE KEY-----\n")
.toString(); .toString();
public static final Node TEST1 = new Node("cluster-1", "cluster-1", "accounting analytics cluster", public static final Node TEST1 = new Node("cluster-1", "cluster-1", "accounting analytics cluster",
"cluster-1.mydomain.com", null, "x86", "rhel", "redhat", "5.3", false, 22, "hadoop", ImmutableList.of("vanilla"), "cluster-1.mydomain.com", null, "x86", "rhel", "redhat", "5.3", false, 22, "hadoop",
"myUser", key, null, "happy bear"); ImmutableList.of("vanilla"), ImmutableMap.of("Name", "foo"), "myUser", key, null, "happy bear");
public static final Node TEST2 = new Node("cluster-1", "cluster-1", "accounting analytics cluster", public static final Node TEST2 = new Node("cluster-1", "cluster-1", "accounting analytics cluster",
"cluster-1.mydomain.com", "virginia", "x86", "rhel", "redhat", "5.3", false, 22, "hadoop", "cluster-1.mydomain.com", "virginia", "x86", "rhel", "redhat", "5.3", false, 22, "hadoop",
ImmutableList.of("vanilla"), "myUser", key, null, "happy bear"); ImmutableList.of("vanilla"), ImmutableMap.of("Name", "foo"), "myUser", key, null, "happy bear");
public static final Node TEST3 = new Node("cluster-2", "cluster-2", "accounting analytics cluster", public static final Node TEST3 = new Node("cluster-2", "cluster-2", "accounting analytics cluster",
"cluster-2.mydomain.com", "maryland", "x86", "rhel", "redhat", "5.3", false, 2022, "hadoop", "cluster-2.mydomain.com", "maryland", "x86", "rhel", "redhat", "5.3", false, 2022, "hadoop",
ImmutableList.of("vanilla"), "myUser", key, null, "happy bear"); ImmutableList.of("vanilla"), ImmutableMap.of("Name", "foo"), "myUser", key, null, "happy bear");
@Test @Test
public void testNodesParse() throws Exception { public void testNodesParse() throws Exception {

View File

@ -10,6 +10,8 @@ nodes:
group: hadoop group: hadoop
tags: tags:
- vanilla - vanilla
metadata:
Name: foo
username: myUser username: myUser
credential: | credential: |
-----BEGIN RSA PRIVATE KEY----- -----BEGIN RSA PRIVATE KEY-----

View File

@ -11,6 +11,8 @@ nodes:
group: hadoop group: hadoop
tags: tags:
- vanilla - vanilla
metadata:
Name: foo
username: myUser username: myUser
credential: | credential: |
-----BEGIN RSA PRIVATE KEY----- -----BEGIN RSA PRIVATE KEY-----
@ -33,6 +35,8 @@ nodes:
group: hadoop group: hadoop
tags: tags:
- vanilla - vanilla
metadata:
Name: foo
username: myUser username: myUser
credential: | credential: |
-----BEGIN RSA PRIVATE KEY----- -----BEGIN RSA PRIVATE KEY-----

View File

@ -10,6 +10,8 @@ nodes:
group: hadoop group: hadoop
tags: tags:
- vanilla - vanilla
metadata:
Name: foo
username: myUser username: myUser
credential_url: classpath:///testkey.txt credential_url: classpath:///testkey.txt
sudo_password: happy bear sudo_password: happy bear

View File

@ -19,18 +19,19 @@
package org.jclouds.cloudservers.compute.strategy; package org.jclouds.cloudservers.compute.strategy;
import static com.google.common.base.Preconditions.checkNotNull; import static com.google.common.base.Preconditions.checkNotNull;
import static org.jclouds.cloudservers.options.CreateServerOptions.Builder.withMetadata;
import java.util.Map; import java.util.Map;
import javax.inject.Inject; import javax.inject.Inject;
import javax.inject.Singleton; import javax.inject.Singleton;
import org.jclouds.cloudservers.CloudServersClient;
import org.jclouds.cloudservers.domain.Server;
import org.jclouds.compute.domain.NodeMetadata; import org.jclouds.compute.domain.NodeMetadata;
import org.jclouds.compute.domain.Template; import org.jclouds.compute.domain.Template;
import org.jclouds.compute.strategy.CreateNodeWithGroupEncodedIntoName; import org.jclouds.compute.strategy.CreateNodeWithGroupEncodedIntoName;
import org.jclouds.domain.Credentials; import org.jclouds.domain.Credentials;
import org.jclouds.cloudservers.CloudServersClient;
import org.jclouds.cloudservers.domain.Server;
import com.google.common.base.Function; import com.google.common.base.Function;
@ -53,8 +54,9 @@ public class CloudServersCreateNodeWithGroupEncodedIntoName implements CreateNod
@Override @Override
public NodeMetadata createNodeWithGroupEncodedIntoName(String group, String name, Template template) { public NodeMetadata createNodeWithGroupEncodedIntoName(String group, String name, Template template) {
Server from = client.createServer(name, Integer.parseInt(template.getImage().getProviderId()), Integer Server from = client.createServer(name, Integer.parseInt(template.getImage().getProviderId()),
.parseInt(template.getHardware().getProviderId())); Integer.parseInt(template.getHardware().getProviderId()),
withMetadata(template.getOptions().getUserMetadata()));
credentialStore.put("node#" + from.getId(), new Credentials("root", from.getAdminPass())); credentialStore.put("node#" + from.getId(), new Credentials("root", from.getAdminPass()));
return serverToNodeMetadata.apply(from); return serverToNodeMetadata.apply(from);
} }

View File

@ -24,6 +24,7 @@ import org.jclouds.compute.domain.NodeMetadata;
import org.jclouds.sshj.config.SshjSshClientModule; import org.jclouds.sshj.config.SshjSshClientModule;
import org.testng.annotations.Test; import org.testng.annotations.Test;
import com.google.common.collect.ImmutableMap;
import com.google.inject.Module; import com.google.inject.Module;
/** /**
@ -40,6 +41,13 @@ public class CloudSigmaComputeServiceLiveTest extends BaseComputeServiceLiveTest
return new SshjSshClientModule(); return new SshjSshClientModule();
} }
// cloudsigma does not support metadata
@Override
protected void checkUserMetadataInNodeEquals(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);
}
protected void checkResponseEqualsHostname(ExecResponse execResponse, NodeMetadata node1) { protected void checkResponseEqualsHostname(ExecResponse execResponse, NodeMetadata node1) {
// hostname is not predictable based on node metadata // hostname is not predictable based on node metadata
assert execResponse.getOutput().trim().equals("ubuntu"); assert execResponse.getOutput().trim().equals("ubuntu");

View File

@ -32,6 +32,7 @@ import org.jclouds.rest.RestContext;
import org.jclouds.sshj.config.SshjSshClientModule; import org.jclouds.sshj.config.SshjSshClientModule;
import org.testng.annotations.Test; import org.testng.annotations.Test;
import com.google.common.collect.ImmutableMap;
import com.google.inject.Module; import com.google.inject.Module;
/** /**
@ -50,6 +51,12 @@ public class DeltacloudComputeServiceLiveTest extends BaseComputeServiceLiveTest
return new SshjSshClientModule(); return new SshjSshClientModule();
} }
// deltacloud does not support metadata
@Override
protected void checkUserMetadataInNodeEquals(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);
}
public void testAssignability() throws Exception { public void testAssignability() throws Exception {
@SuppressWarnings("unused") @SuppressWarnings("unused")
RestContext<DeltacloudClient, DeltacloudAsyncClient> tmContext = new ComputeServiceContextFactory() RestContext<DeltacloudClient, DeltacloudAsyncClient> tmContext = new ComputeServiceContextFactory()

View File

@ -89,6 +89,11 @@ public class RunningInstanceToNodeMetadata implements Function<RunningInstance,
if (instance == null || instance.getId() == null) if (instance == null || instance.getId() == null)
return null; return null;
NodeMetadataBuilder builder = new NodeMetadataBuilder(); NodeMetadataBuilder builder = new NodeMetadataBuilder();
builder = buildInstance(instance, builder);
return builder.build();
}
protected NodeMetadataBuilder buildInstance(RunningInstance instance, NodeMetadataBuilder builder) {
builder.providerId(instance.getId()); builder.providerId(instance.getId());
builder.id(instance.getRegion() + "/" + instance.getId()); builder.id(instance.getRegion() + "/" + instance.getId());
String group = getGroupForInstance(instance); String group = getGroupForInstance(instance);
@ -116,8 +121,7 @@ public class RunningInstanceToNodeMetadata implements Function<RunningInstance,
} catch (UncheckedExecutionException e) { } catch (UncheckedExecutionException e) {
logger.debug("error getting image for %s: %s", regionAndName, e); logger.debug("error getting image for %s: %s", regionAndName, e);
} }
return builder;
return builder.build();
} }
protected void addCredentialsForInstance(NodeMetadataBuilder builder, RunningInstance instance) { protected void addCredentialsForInstance(NodeMetadataBuilder builder, RunningInstance instance) {

View File

@ -23,10 +23,9 @@ import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.base.Preconditions.checkState; import static com.google.common.base.Preconditions.checkState;
import java.util.Arrays; import java.util.Arrays;
import java.util.Map;
import java.util.Set; import java.util.Set;
import org.jclouds.javax.annotation.Nullable;
import org.jclouds.compute.options.TemplateOptions; import org.jclouds.compute.options.TemplateOptions;
import org.jclouds.domain.Credentials; import org.jclouds.domain.Credentials;
import org.jclouds.ec2.domain.BlockDeviceMapping; import org.jclouds.ec2.domain.BlockDeviceMapping;
@ -35,6 +34,7 @@ import org.jclouds.ec2.domain.BlockDeviceMapping.MapEphemeralDeviceToDevice;
import org.jclouds.ec2.domain.BlockDeviceMapping.MapNewVolumeToDevice; import org.jclouds.ec2.domain.BlockDeviceMapping.MapNewVolumeToDevice;
import org.jclouds.ec2.domain.BlockDeviceMapping.UnmapDeviceNamed; import org.jclouds.ec2.domain.BlockDeviceMapping.UnmapDeviceNamed;
import org.jclouds.io.Payload; import org.jclouds.io.Payload;
import org.jclouds.javax.annotation.Nullable;
import org.jclouds.scriptbuilder.domain.Statement; import org.jclouds.scriptbuilder.domain.Statement;
import org.jclouds.util.Preconditions2; import org.jclouds.util.Preconditions2;
@ -42,11 +42,11 @@ import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Iterables; import com.google.common.collect.Iterables;
/** /**
* Contains options supported in the {@code ComputeService#runNode} operation on the "ec2" provider. * Contains options supported in the {@code ComputeService#runNode} operation on
* <h2> * the "ec2" provider. <h2>
* Usage</h2> The recommended way to instantiate a EC2TemplateOptions object is to statically import * Usage</h2> The recommended way to instantiate a EC2TemplateOptions object is
* EC2TemplateOptions.* and invoke a static creation method followed by an instance mutator (if * to statically import EC2TemplateOptions.* and invoke a static creation method
* needed): * followed by an instance mutator (if needed):
* <p/> * <p/>
* <code> * <code>
* import static org.jclouds.aws.ec2.compute.options.EC2TemplateOptions.Builder.*; * import static org.jclouds.aws.ec2.compute.options.EC2TemplateOptions.Builder.*;
@ -292,13 +292,20 @@ public class EC2TemplateOptions extends TemplateOptions implements Cloneable {
} }
/** /**
* @see TemplateOptions#withDetails * @see TemplateOptions#userMetadata(Map)
*/ */
public static EC2TemplateOptions withDetails() { public static EC2TemplateOptions userMetadata(Map<String, String> userMetadata) {
EC2TemplateOptions options = new EC2TemplateOptions(); EC2TemplateOptions options = new EC2TemplateOptions();
return EC2TemplateOptions.class.cast(options.withMetadata()); return EC2TemplateOptions.class.cast(options.userMetadata(userMetadata));
} }
/**
* @see TemplateOptions#userMetadata(String, String)
*/
public static EC2TemplateOptions userMetadata(String key, String value) {
EC2TemplateOptions options = new EC2TemplateOptions();
return EC2TemplateOptions.class.cast(options.userMetadata(key, value));
}
} }
// methods that only facilitate returning the correct object type // methods that only facilitate returning the correct object type
@ -370,14 +377,6 @@ public class EC2TemplateOptions extends TemplateOptions implements Cloneable {
return EC2TemplateOptions.class.cast(super.runScript(script)); return EC2TemplateOptions.class.cast(super.runScript(script));
} }
/**
* {@inheritDoc}
*/
@Override
public EC2TemplateOptions withMetadata() {
return EC2TemplateOptions.class.cast(super.withMetadata());
}
/** /**
* {@inheritDoc} * {@inheritDoc}
*/ */
@ -427,15 +426,32 @@ public class EC2TemplateOptions extends TemplateOptions implements Cloneable {
} }
/** /**
* @return groupNames the user specified to run instances with, or zero length set to create an * {@inheritDoc}
* implicit group */
@Override
public EC2TemplateOptions userMetadata(Map<String, String> userMetadata) {
return EC2TemplateOptions.class.cast(super.userMetadata(userMetadata));
}
/**
* {@inheritDoc}
*/
@Override
public EC2TemplateOptions userMetadata(String key, String value) {
return EC2TemplateOptions.class.cast(super.userMetadata(key, value));
}
/**
* @return groupNames the user specified to run instances with, or zero
* length set to create an implicit group
*/ */
public Set<String> getGroups() { public Set<String> getGroups() {
return groupNames; return groupNames;
} }
/** /**
* @return keyPair to use when running the instance or null, to generate a keypair. * @return keyPair to use when running the instance or null, to generate a
* keypair.
*/ */
public String getKeyPair() { public String getKeyPair() {
return keyPair; return keyPair;

View File

@ -52,6 +52,7 @@ import org.jclouds.sshj.config.SshjSshClientModule;
import org.testng.annotations.Test; import org.testng.annotations.Test;
import com.google.common.base.Predicate; import com.google.common.base.Predicate;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSortedSet; import com.google.common.collect.ImmutableSortedSet;
import com.google.common.collect.Iterables; import com.google.common.collect.Iterables;
import com.google.common.collect.Sets; import com.google.common.collect.Sets;
@ -73,6 +74,14 @@ public class EC2ComputeServiceLiveTest extends BaseComputeServiceLiveTest {
return new SshjSshClientModule(); return new SshjSshClientModule();
} }
// normal ec2 does not support metadata
@Override
protected void checkUserMetadataInNodeEquals(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);
}
@Test(enabled = true, dependsOnMethods = "testCorrectAuthException") @Test(enabled = true, dependsOnMethods = "testCorrectAuthException")
public void testImagesResolveCorrectly() { public void testImagesResolveCorrectly() {
Template defaultTemplate = client.templateBuilder().build(); Template defaultTemplate = client.templateBuilder().build();

View File

@ -24,6 +24,7 @@ import org.jclouds.compute.domain.NodeMetadata;
import org.jclouds.sshj.config.SshjSshClientModule; import org.jclouds.sshj.config.SshjSshClientModule;
import org.testng.annotations.Test; import org.testng.annotations.Test;
import com.google.common.collect.ImmutableMap;
import com.google.inject.Module; import com.google.inject.Module;
/** /**
@ -40,6 +41,13 @@ public class ElasticStackComputeServiceLiveTest extends BaseComputeServiceLiveTe
return new SshjSshClientModule(); return new SshjSshClientModule();
} }
// elasticstack does not support metadata
@Override
protected void checkUserMetadataInNodeEquals(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);
}
@Override @Override
public void testOptionToNotBlock() { public void testOptionToNotBlock() {
// start call is blocking anyway. // start call is blocking anyway.

View File

@ -19,6 +19,7 @@
package org.jclouds.openstack.nova.compute.strategy; package org.jclouds.openstack.nova.compute.strategy;
import static com.google.common.base.Preconditions.checkNotNull; import static com.google.common.base.Preconditions.checkNotNull;
import static org.jclouds.openstack.nova.options.CreateServerOptions.Builder.withMetadata;
import java.util.Map; import java.util.Map;
@ -53,7 +54,8 @@ public class NovaCreateNodeWithGroupEncodedIntoName implements CreateNodeWithGro
@Override @Override
public NodeMetadata createNodeWithGroupEncodedIntoName(String group, String name, Template template) { public NodeMetadata createNodeWithGroupEncodedIntoName(String group, String name, Template template) {
Server from = client.createServer(name, template.getImage().getId(), template.getHardware().getId()); Server from = client.createServer(name, template.getImage().getId(), template.getHardware().getId(),
withMetadata(template.getOptions().getUserMetadata()));
credentialStore.put("node#" + from.getId(), new Credentials("root", from.getAdminPass())); credentialStore.put("node#" + from.getId(), new Credentials("root", from.getAdminPass()));
return serverToNodeMetadata.apply(from); return serverToNodeMetadata.apply(from);
} }

View File

@ -38,7 +38,6 @@ import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException; import java.util.concurrent.TimeoutException;
import com.google.common.collect.Iterables;
import org.jclouds.compute.ComputeService; import org.jclouds.compute.ComputeService;
import org.jclouds.compute.ComputeServiceContext; import org.jclouds.compute.ComputeServiceContext;
import org.jclouds.compute.ComputeServiceContextFactory; import org.jclouds.compute.ComputeServiceContextFactory;

View File

@ -50,6 +50,7 @@ import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeoutException; import java.util.concurrent.TimeoutException;
import net.schmizz.sshj.userauth.UserAuthException; import net.schmizz.sshj.userauth.UserAuthException;
import org.jclouds.compute.ComputeServiceContext; import org.jclouds.compute.ComputeServiceContext;
import org.jclouds.compute.ComputeServiceContextFactory; import org.jclouds.compute.ComputeServiceContextFactory;
import org.jclouds.compute.RunNodesException; import org.jclouds.compute.RunNodesException;
@ -352,13 +353,6 @@ public class NovaComputeServiceLiveTest extends ComputeBase {
//checkHttpGet(node); //checkHttpGet(node);
} }
@Test(timeOut = 60000)
public void testTemplateOptions() throws Exception {
TemplateOptions options = new TemplateOptions().withMetadata();
Template t = getDefaultTemplateBuilder().smallest().options(options).build();
assert t.getOptions().isIncludeMetadata() : "The metadata option should be 'true' " + "for the created template";
}
public void testListImages() throws Exception { public void testListImages() throws Exception {
for (Image image : computeService.listImages()) { for (Image image : computeService.listImages()) {
assert image.getProviderId() != null : image; assert image.getProviderId() != null : image;

View File

@ -19,6 +19,7 @@
package org.jclouds.vcloud.compute.options; package org.jclouds.vcloud.compute.options;
import java.util.Arrays; import java.util.Arrays;
import java.util.Map;
import org.jclouds.compute.options.TemplateOptions; import org.jclouds.compute.options.TemplateOptions;
import org.jclouds.io.Payload; import org.jclouds.io.Payload;
@ -164,11 +165,19 @@ public class VCloudTemplateOptions extends TemplateOptions implements Cloneable
} }
/** /**
* @see TemplateOptions#withDetails * @see TemplateOptions#userMetadata(Map)
*/ */
public static VCloudTemplateOptions withDetails() { public static VCloudTemplateOptions userMetadata(Map<String, String> userMetadata) {
VCloudTemplateOptions options = new VCloudTemplateOptions(); VCloudTemplateOptions options = new VCloudTemplateOptions();
return VCloudTemplateOptions.class.cast(options.withMetadata()); return VCloudTemplateOptions.class.cast(options.userMetadata(userMetadata));
}
/**
* @see TemplateOptions#userMetadata(String, String)
*/
public static VCloudTemplateOptions userMetadata(String key, String value) {
VCloudTemplateOptions options = new VCloudTemplateOptions();
return VCloudTemplateOptions.class.cast(options.userMetadata(key, value));
} }
} }
@ -270,11 +279,19 @@ public class VCloudTemplateOptions extends TemplateOptions implements Cloneable
} }
/** /**
* @see TemplateOptions#withMetadata * {@inheritDoc}
*/ */
@Override @Override
public VCloudTemplateOptions withMetadata() { public VCloudTemplateOptions userMetadata(Map<String, String> userMetadata) {
return VCloudTemplateOptions.class.cast(super.withMetadata()); return VCloudTemplateOptions.class.cast(super.userMetadata(userMetadata));
}
/**
* {@inheritDoc}
*/
@Override
public VCloudTemplateOptions userMetadata(String key, String value) {
return VCloudTemplateOptions.class.cast(super.userMetadata(key, value));
} }
@Override @Override
@ -317,7 +334,7 @@ public class VCloudTemplateOptions extends TemplateOptions implements Cloneable
+ ", ipAddressAllocationMode=" + ipAddressAllocationMode + ", inboundPorts=" + ", ipAddressAllocationMode=" + ipAddressAllocationMode + ", inboundPorts="
+ Arrays.toString(inboundPorts) + ", privateKey=" + (privateKey != null) + ", publicKey=" + Arrays.toString(inboundPorts) + ", privateKey=" + (privateKey != null) + ", publicKey="
+ (publicKey != null) + ", runScript=" + (script != null) + ", port:seconds=" + port + ":" + seconds + (publicKey != null) + ", runScript=" + (script != null) + ", port:seconds=" + port + ":" + seconds
+ ", metadata/details: " + includeMetadata + "]"; + ", userMetadata: " + userMetadata + "]";
} }
} }

View File

@ -32,6 +32,7 @@ import org.jclouds.vcloud.VCloudClient;
import org.jclouds.vcloud.domain.VApp; import org.jclouds.vcloud.domain.VApp;
import org.testng.annotations.Test; import org.testng.annotations.Test;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet; import com.google.common.collect.ImmutableSet;
import com.google.inject.Module; import com.google.inject.Module;
@ -40,7 +41,7 @@ import com.google.inject.Module;
* *
* @author Adrian Cole * @author Adrian Cole
*/ */
@Test(groups = "live", enabled = true, sequential = true) @Test(groups = "live", enabled = true, singleThreaded = true)
public class VCloudComputeServiceLiveTest extends BaseComputeServiceLiveTest { public class VCloudComputeServiceLiveTest extends BaseComputeServiceLiveTest {
public VCloudComputeServiceLiveTest() { public VCloudComputeServiceLiveTest() {
@ -52,6 +53,13 @@ public class VCloudComputeServiceLiveTest extends BaseComputeServiceLiveTest {
return new SshjSshClientModule(); return new SshjSshClientModule();
} }
// vcloud does not support metadata
@Override
protected void checkUserMetadataInNodeEquals(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);
}
public void testAssignability() throws Exception { public void testAssignability() throws Exception {
@SuppressWarnings("unused") @SuppressWarnings("unused")
RestContext<VCloudClient, VCloudAsyncClient> tmContext = new ComputeServiceContextFactory(setupRestProperties()) RestContext<VCloudClient, VCloudAsyncClient> tmContext = new ComputeServiceContextFactory(setupRestProperties())

View File

@ -22,16 +22,18 @@ import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.base.Preconditions.checkState; import static com.google.common.base.Preconditions.checkState;
import java.util.Arrays; import java.util.Arrays;
import java.util.Map;
import org.jclouds.compute.options.TemplateOptions; import org.jclouds.compute.options.TemplateOptions;
import org.jclouds.io.Payload; import org.jclouds.io.Payload;
import org.jclouds.util.Preconditions2; import org.jclouds.util.Preconditions2;
/** /**
* Contains options supported in the {@code ComputeService#runNode} operation on the * Contains options supported in the {@code ComputeService#runNode} operation on
* "trmk-vcloudexpress" provider. <h2> * the "trmk-vcloudexpress" provider. <h2>
* Usage</h2> The recommended way to instantiate a TerremarkVCloudTemplateOptions object is to * Usage</h2> The recommended way to instantiate a
* statically import TerremarkVCloudTemplateOptions.* and invoke a static creation method followed * TerremarkVCloudTemplateOptions object is to statically import
* TerremarkVCloudTemplateOptions.* and invoke a static creation method followed
* by an instance mutator (if needed): * by an instance mutator (if needed):
* <p/> * <p/>
* <code> * <code>
@ -157,13 +159,20 @@ public class TerremarkVCloudTemplateOptions extends TemplateOptions implements C
} }
/** /**
* @see TemplateOptions#withDetails * @see TemplateOptions#userMetadata(Map)
*/ */
public static TerremarkVCloudTemplateOptions withDetails() { public static TerremarkVCloudTemplateOptions userMetadata(Map<String, String> userMetadata) {
TerremarkVCloudTemplateOptions options = new TerremarkVCloudTemplateOptions(); TerremarkVCloudTemplateOptions options = new TerremarkVCloudTemplateOptions();
return TerremarkVCloudTemplateOptions.class.cast(options.withMetadata()); return TerremarkVCloudTemplateOptions.class.cast(options.userMetadata(userMetadata));
} }
/**
* @see TemplateOptions#userMetadata(String, String)
*/
public static TerremarkVCloudTemplateOptions userMetadata(String key, String value) {
TerremarkVCloudTemplateOptions options = new TerremarkVCloudTemplateOptions();
return TerremarkVCloudTemplateOptions.class.cast(options.userMetadata(key, value));
}
} }
// methods that only facilitate returning the correct object type // methods that only facilitate returning the correct object type
@ -178,9 +187,10 @@ public class TerremarkVCloudTemplateOptions extends TemplateOptions implements C
/** /**
* *
* special thing is that we do assume if you are passing groups that you have everything you need * special thing is that we do assume if you are passing groups that you have
* already defined. for example, our option inboundPorts normally creates ingress rules * everything you need already defined. for example, our option inboundPorts
* accordingly but if we notice you've specified securityGroups, we do not mess with rules at all * normally creates ingress rules accordingly but if we notice you've
* specified securityGroups, we do not mess with rules at all
* *
* @see TemplateOptions#inboundPorts * @see TemplateOptions#inboundPorts
*/ */
@ -241,15 +251,23 @@ public class TerremarkVCloudTemplateOptions extends TemplateOptions implements C
} }
/** /**
* @see TemplateOptions#withMetadata * @see TemplateOptions#userMetadata
*/ */
@Override public TerremarkVCloudTemplateOptions userMetadata(Map<String, String> userMetadata) {
public TerremarkVCloudTemplateOptions withMetadata() { return TerremarkVCloudTemplateOptions.class.cast(super.userMetadata(userMetadata));
return TerremarkVCloudTemplateOptions.class.cast(super.withMetadata());
} }
/** /**
* @return keyPair to use when running the instance or null, to generate a keypair. * {@inheritDoc}
*/
@Override
public TerremarkVCloudTemplateOptions userMetadata(String key, String value) {
return TerremarkVCloudTemplateOptions.class.cast(super.userMetadata(key, value));
}
/**
* @return keyPair to use when running the instance or null, to generate a
* keypair.
*/ */
public String getSshKeyFingerprint() { public String getSshKeyFingerprint() {
return keyPair; return keyPair;
@ -295,7 +313,7 @@ public class TerremarkVCloudTemplateOptions extends TemplateOptions implements C
return "TerremarkVCloudTemplateOptions [keyPair=" + keyPair + ", noKeyPair=" + noKeyPair + ", inboundPorts=" return "TerremarkVCloudTemplateOptions [keyPair=" + keyPair + ", noKeyPair=" + noKeyPair + ", inboundPorts="
+ Arrays.toString(inboundPorts) + ", privateKey=" + (privateKey != null) + ", publicKey=" + Arrays.toString(inboundPorts) + ", privateKey=" + (privateKey != null) + ", publicKey="
+ (publicKey != null) + ", runScript=" + (script != null) + ", port:seconds=" + port + ":" + seconds + (publicKey != null) + ", runScript=" + (script != null) + ", port:seconds=" + port + ":" + seconds
+ ", metadata/details: " + includeMetadata + "]"; + ", userMetadata: " + userMetadata + "]";
} }
} }

View File

@ -23,6 +23,7 @@ import static com.google.common.base.Preconditions.checkNotNull;
import java.io.IOException; import java.io.IOException;
import java.util.Arrays; import java.util.Arrays;
import java.util.Map;
import java.util.Set; import java.util.Set;
import org.jclouds.compute.domain.NodeState; import org.jclouds.compute.domain.NodeState;
@ -34,12 +35,14 @@ import org.jclouds.util.Strings2;
import com.google.common.base.Throwables; import com.google.common.base.Throwables;
import com.google.common.collect.ImmutableSet; import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Maps;
/** /**
* Contains options supported in the {@code ComputeService#runNodesWithTag} operation. <h2> * Contains options supported in the {@code ComputeService#runNodesWithTag}
* Usage</h2> The recommended way to instantiate a TemplateOptions object is to statically import * operation. <h2>
* TemplateOptions.* and invoke a static creation method followed by an instance mutator (if * Usage</h2> The recommended way to instantiate a TemplateOptions object is to
* needed): * statically import TemplateOptions.* and invoke a static creation method
* followed by an instance mutator (if needed):
* <p/> * <p/>
* <code> * <code>
* import static org.jclouds.compute.options.TemplateOptions.Builder.*; * import static org.jclouds.compute.options.TemplateOptions.Builder.*;
@ -71,8 +74,8 @@ public class TemplateOptions extends RunScriptOptions implements Cloneable {
to.authorizePublicKey(this.getPublicKey()); to.authorizePublicKey(this.getPublicKey());
if (this.getPort() != -1) if (this.getPort() != -1)
to.blockOnPort(this.getPort(), this.getSeconds()); to.blockOnPort(this.getPort(), this.getSeconds());
if (this.isIncludeMetadata()) if (this.getUserMetadata().size() > 0)
to.withMetadata(); to.userMetadata(this.getUserMetadata());
if (this.getTags().size() > 0) if (this.getTags().size() > 0)
to.tags(getTags()); to.tags(getTags());
if (!this.shouldBlockUntilRunning()) if (!this.shouldBlockUntilRunning())
@ -266,19 +269,34 @@ public class TemplateOptions extends RunScriptOptions implements Cloneable {
throw new IllegalArgumentException("privateKey is immutable"); throw new IllegalArgumentException("privateKey is immutable");
} }
@Override
public boolean isIncludeMetadata() {
return delegate.isIncludeMetadata();
}
@Override @Override
public TemplateOptions runScript(byte[] script) { public TemplateOptions runScript(byte[] script) {
throw new IllegalArgumentException("script is immutable"); throw new IllegalArgumentException("script is immutable");
} }
@Override @Override
public TemplateOptions withMetadata() { public Set<String> getTags() {
throw new IllegalArgumentException("metadata is immutable"); return delegate.getTags();
}
@Override
public TemplateOptions tags(Iterable<String> tags) {
throw new IllegalArgumentException("tags are immutable");
}
@Override
public TemplateOptions userMetadata(Map<String, String> userMetadata) {
throw new IllegalArgumentException("userMetadata is immutable");
}
@Override
public TemplateOptions userMetadata(String key, String value) {
throw new IllegalArgumentException("userMetadata is immutable");
}
@Override
public Map<String, String> getUserMetadata() {
return delegate.getUserMetadata();
} }
} }
@ -293,10 +311,10 @@ public class TemplateOptions extends RunScriptOptions implements Cloneable {
protected String publicKey; protected String publicKey;
protected boolean includeMetadata;
protected boolean blockUntilRunning = true; protected boolean blockUntilRunning = true;
protected Map<String, String> userMetadata = Maps.newLinkedHashMap();
public int[] getInboundPorts() { public int[] getInboundPorts() {
return inboundPorts; return inboundPorts;
} }
@ -317,10 +335,6 @@ public class TemplateOptions extends RunScriptOptions implements Cloneable {
return publicKey; return publicKey;
} }
public boolean isIncludeMetadata() {
return includeMetadata;
}
/** /**
* @see TemplateOptions#blockUntilRunning(boolean) * @see TemplateOptions#blockUntilRunning(boolean)
*/ */
@ -334,7 +348,9 @@ public class TemplateOptions extends RunScriptOptions implements Cloneable {
/** /**
* <p/> * <p/>
* please use alternative that uses the {@link org.jclouds.scriptbuilder.domain.Statement} object * please use alternative that uses the
* {@link org.jclouds.scriptbuilder.domain.Statement} object
*
* @see TemplateOptions#runScript(Statement) * @see TemplateOptions#runScript(Statement)
* @see org.jclouds.io.Payloads * @see org.jclouds.io.Payloads
*/ */
@ -357,8 +373,8 @@ public class TemplateOptions extends RunScriptOptions implements Cloneable {
} }
/** /**
* This script will be executed as the root user upon system startup. This script gets a * This script will be executed as the root user upon system startup. This
* prologue, so no #!/bin/bash required, path set up, etc * script gets a prologue, so no #!/bin/bash required, path set up, etc
* *
*/ */
public TemplateOptions runScript(Statement script) { public TemplateOptions runScript(Statement script) {
@ -442,11 +458,6 @@ public class TemplateOptions extends RunScriptOptions implements Cloneable {
return this; return this;
} }
public TemplateOptions withMetadata() {
this.includeMetadata = true;
return this;
}
public static class Builder extends org.jclouds.compute.options.RunScriptOptions.Builder { public static class Builder extends org.jclouds.compute.options.RunScriptOptions.Builder {
public static TemplateOptions nameTask(String name) { public static TemplateOptions nameTask(String name) {
@ -506,7 +517,7 @@ public class TemplateOptions extends RunScriptOptions implements Cloneable {
return options.blockUntilRunning(blockUntilRunning); return options.blockUntilRunning(blockUntilRunning);
} }
/** /**
* please use alternative that uses the {@link Statement) object * please use alternative that uses the {@link Statement) object
* *
* @see TemplateOptions#runScript(Statement) * @see TemplateOptions#runScript(Statement)
@ -535,7 +546,8 @@ public class TemplateOptions extends RunScriptOptions implements Cloneable {
} }
/** /**
* please use alternative that uses the {@link org.jclouds.io.Payload} object * please use alternative that uses the {@link org.jclouds.io.Payload}
* object
* *
* @see org.jclouds.io.Payloads * @see org.jclouds.io.Payloads
* @see #installPrivateKey(Payload) * @see #installPrivateKey(Payload)
@ -556,7 +568,8 @@ public class TemplateOptions extends RunScriptOptions implements Cloneable {
} }
/** /**
* please use alternative that uses the {@link org.jclouds.io.Payload} object * please use alternative that uses the {@link org.jclouds.io.Payload}
* object
* *
* @see org.jclouds.io.Payloads * @see org.jclouds.io.Payloads
* @see #authorizePublicKey(Payload) * @see #authorizePublicKey(Payload)
@ -576,9 +589,20 @@ public class TemplateOptions extends RunScriptOptions implements Cloneable {
return options.authorizePublicKey(rsaKey); return options.authorizePublicKey(rsaKey);
} }
public static TemplateOptions withDetails() { /**
* @see TemplateOptions#userMetadata(Map)
*/
public static TemplateOptions userMetadata(Map<String, String> userMetadata) {
TemplateOptions options = new TemplateOptions(); TemplateOptions options = new TemplateOptions();
return options.withMetadata(); return options.userMetadata(userMetadata);
}
/**
* @see TemplateOptions#userMetadata(String, String)
*/
public static TemplateOptions userMetadata(String key, String value) {
TemplateOptions options = new TemplateOptions();
return options.userMetadata(key, value);
} }
public static TemplateOptions blockOnComplete(boolean value) { public static TemplateOptions blockOnComplete(boolean value) {
@ -592,8 +616,8 @@ public class TemplateOptions extends RunScriptOptions implements Cloneable {
public String toString() { public String toString() {
return "[inboundPorts=" + Arrays.toString(inboundPorts) + ", privateKey=" + (privateKey != null) + ", publicKey=" return "[inboundPorts=" + Arrays.toString(inboundPorts) + ", privateKey=" + (privateKey != null) + ", publicKey="
+ (publicKey != null) + ", runScript=" + (script != null) + ", blockUntilRunning=" + blockUntilRunning + (publicKey != null) + ", runScript=" + (script != null) + ", blockUntilRunning=" + blockUntilRunning
+ ", blockOnComplete=" + blockOnComplete + ", port:seconds=" + port + ":" + seconds + ", blockOnComplete=" + blockOnComplete + ", port:seconds=" + port + ":" + seconds + ", userMetadata: "
+ ", metadata/details: " + includeMetadata + "]"; + userMetadata + "]";
} }
/** /**
@ -613,14 +637,43 @@ public class TemplateOptions extends RunScriptOptions implements Cloneable {
return this; return this;
} }
/**
*
* @param userMetadata
* user-defined metadata to assign to this server
*/
public TemplateOptions userMetadata(Map<String, String> userMetadata) {
this.userMetadata.putAll(checkNotNull(userMetadata, "userMetadata"));
return this;
}
/**
*
* @param key
* key to place into the metadata map
* @param value
* value to associate with that key
*/
public TemplateOptions userMetadata(String key, String value) {
this.userMetadata.put(checkNotNull(key, "key"), checkNotNull(value, "value"));
return this;
}
/**
* @see #userMetadata(Map)
*/
public Map<String, String> getUserMetadata() {
return userMetadata;
}
@Override @Override
public int hashCode() { public int hashCode() {
final int prime = 31; final int prime = 31;
int result = 1; int result = 1;
result = prime * result + (blockUntilRunning ? 1231 : 1237); result = prime * result + (blockUntilRunning ? 1231 : 1237);
result = prime * result + Arrays.hashCode(inboundPorts); result = prime * result + Arrays.hashCode(inboundPorts);
result = prime * result + (includeMetadata ? 1231 : 1237);
result = prime * result + port; result = prime * result + port;
result = prime * result + ((userMetadata == null) ? 0 : userMetadata.hashCode());
result = prime * result + ((privateKey == null) ? 0 : privateKey.hashCode()); result = prime * result + ((privateKey == null) ? 0 : privateKey.hashCode());
result = prime * result + ((publicKey == null) ? 0 : publicKey.hashCode()); result = prime * result + ((publicKey == null) ? 0 : publicKey.hashCode());
result = prime * result + ((script == null) ? 0 : script.hashCode()); result = prime * result + ((script == null) ? 0 : script.hashCode());
@ -641,7 +694,10 @@ public class TemplateOptions extends RunScriptOptions implements Cloneable {
return false; return false;
if (!Arrays.equals(inboundPorts, other.inboundPorts)) if (!Arrays.equals(inboundPorts, other.inboundPorts))
return false; return false;
if (includeMetadata != other.includeMetadata) if (userMetadata == null) {
if (other.userMetadata != null)
return false;
} else if (!userMetadata.equals(other.userMetadata))
return false; return false;
if (port != other.port) if (port != other.port)
return false; return false;

View File

@ -92,6 +92,7 @@ public class StubComputeServiceAdapter implements JCloudsNativeComputeServiceAda
// using a predictable name so tests will pass // using a predictable name so tests will pass
builder.hostname(group); builder.hostname(group);
builder.tags(template.getOptions().getTags()); builder.tags(template.getOptions().getTags());
builder.userMetadata(template.getOptions().getUserMetadata());
builder.group(group); builder.group(group);
builder.location(location.get()); builder.location(location.get());
builder.imageId(template.getImage().getId()); builder.imageId(template.getImage().getId());

View File

@ -50,11 +50,11 @@ import java.io.FileNotFoundException;
import java.io.IOException; import java.io.IOException;
import java.util.Collection; import java.util.Collection;
import java.util.Map; import java.util.Map;
import java.util.Map.Entry;
import java.util.NoSuchElementException; import java.util.NoSuchElementException;
import java.util.Properties; import java.util.Properties;
import java.util.Set; import java.util.Set;
import java.util.SortedSet; import java.util.SortedSet;
import java.util.Map.Entry;
import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException; import java.util.concurrent.TimeoutException;
@ -96,6 +96,7 @@ import com.google.common.base.Function;
import com.google.common.base.Predicate; import com.google.common.base.Predicate;
import com.google.common.base.Predicates; import com.google.common.base.Predicates;
import com.google.common.base.Supplier; import com.google.common.base.Supplier;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet; import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Iterables; import com.google.common.collect.Iterables;
import com.google.inject.Guice; import com.google.inject.Guice;
@ -531,7 +532,8 @@ public abstract class BaseComputeServiceLiveTest {
assertEquals(toDestroy, destroyed.size()); assertEquals(toDestroy, destroyed.size());
for (NodeMetadata node : filter(client.listNodesDetailsMatching(all()), inGroup(group))) { for (NodeMetadata node : filter(client.listNodesDetailsMatching(all()), inGroup(group))) {
assert node.getState() == NodeState.TERMINATED : node; assert node.getState() == NodeState.TERMINATED : node;
assertEquals(context.getCredentialStore().get("node#" + node.getId()), null); assert context.getCredentialStore().get("node#" + node.getId()) == null : "credential should have been null for "
+ "node#" + node.getId();
} }
} }
@ -595,12 +597,16 @@ public abstract class BaseComputeServiceLiveTest {
} }
try { try {
ImmutableMap<String, String> userMetadata = ImmutableMap.<String, String> of("Name", group);
long startSeconds = currentTimeMillis(); long startSeconds = currentTimeMillis();
NodeMetadata node = getOnlyElement(client.createNodesInGroup(group, 1, inboundPorts(22, 8080).blockOnPort(22, NodeMetadata node = getOnlyElement(client.createNodesInGroup(group, 1,
300))); inboundPorts(22, 8080).blockOnPort(22, 300)
.userMetadata(userMetadata)));
final String nodeId = node.getId(); final String nodeId = node.getId();
long createSeconds = (currentTimeMillis() - startSeconds) / 1000; long createSeconds = (currentTimeMillis() - startSeconds) / 1000;
checkUserMetadataInNodeEquals(node, userMetadata);
getAnonymousLogger().info( getAnonymousLogger().info(
format("<< available node(%s) os(%s) in %ss", node.getId(), node.getOperatingSystem(), createSeconds)); format("<< available node(%s) os(%s) in %ss", node.getId(), node.getOperatingSystem(), createSeconds));
@ -656,11 +662,9 @@ public abstract class BaseComputeServiceLiveTest {
} }
@Test(enabled = true/* , dependsOnMethods = "testCompareSizes" */) protected void checkUserMetadataInNodeEquals(NodeMetadata node, ImmutableMap<String, String> userMetadata) {
public void testTemplateOptions() throws Exception { assert node.getUserMetadata().equals(userMetadata) : String.format("node userMetadata did not match %s %s",
TemplateOptions options = new TemplateOptions().withMetadata(); userMetadata, node);
Template t = client.templateBuilder().smallest().options(options).build();
assert t.getOptions().isIncludeMetadata() : "The metadata option should be 'true' " + "for the created template";
} }
public void testListImages() throws Exception { public void testListImages() throws Exception {

View File

@ -23,6 +23,7 @@ import static com.google.common.base.Preconditions.checkNotNull;
import java.net.URI; import java.net.URI;
import java.util.Map; import java.util.Map;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Maps; import com.google.common.collect.Maps;
/** /**
@ -57,7 +58,7 @@ public abstract class ResourceMetadataBuilder<T extends Enum<T>> {
} }
public ResourceMetadataBuilder<T> userMetadata(Map<String, String> userMetadata) { public ResourceMetadataBuilder<T> userMetadata(Map<String, String> userMetadata) {
this.userMetadata = checkNotNull(userMetadata, "userMetadata"); this.userMetadata = ImmutableMap.copyOf(checkNotNull(userMetadata, "userMetadata"));
return this; return this;
} }
} }

View File

@ -19,6 +19,7 @@
package org.jclouds.aws.ec2.compute; package org.jclouds.aws.ec2.compute;
import static com.google.common.base.Preconditions.checkState; import static com.google.common.base.Preconditions.checkState;
import static com.google.common.collect.Iterables.transform;
import java.util.Map; import java.util.Map;
import java.util.Map.Entry; import java.util.Map.Entry;
@ -34,12 +35,16 @@ import org.jclouds.Constants;
import org.jclouds.aws.ec2.AWSEC2Client; import org.jclouds.aws.ec2.AWSEC2Client;
import org.jclouds.aws.ec2.domain.PlacementGroup; import org.jclouds.aws.ec2.domain.PlacementGroup;
import org.jclouds.aws.ec2.domain.PlacementGroup.State; import org.jclouds.aws.ec2.domain.PlacementGroup.State;
import org.jclouds.aws.util.AWSUtils;
import org.jclouds.collect.Memoized; import org.jclouds.collect.Memoized;
import org.jclouds.compute.ComputeServiceContext; import org.jclouds.compute.ComputeServiceContext;
import org.jclouds.compute.RunNodesException;
import org.jclouds.compute.callables.RunScriptOnNode; import org.jclouds.compute.callables.RunScriptOnNode;
import org.jclouds.compute.domain.Hardware; import org.jclouds.compute.domain.Hardware;
import org.jclouds.compute.domain.Image; import org.jclouds.compute.domain.Image;
import org.jclouds.compute.domain.NodeMetadata; 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.domain.TemplateBuilder;
import org.jclouds.compute.internal.PersistNodeCredentials; import org.jclouds.compute.internal.PersistNodeCredentials;
import org.jclouds.compute.options.TemplateOptions; import org.jclouds.compute.options.TemplateOptions;
@ -62,9 +67,12 @@ import org.jclouds.scriptbuilder.functions.InitAdminAccess;
import org.jclouds.util.Preconditions2; import org.jclouds.util.Preconditions2;
import com.google.common.annotations.VisibleForTesting; import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Function;
import com.google.common.base.Predicate; import com.google.common.base.Predicate;
import com.google.common.base.Supplier; import com.google.common.base.Supplier;
import com.google.common.cache.Cache; import com.google.common.cache.Cache;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Iterables;
/** /**
* @author Adrian Cole * @author Adrian Cole
@ -91,7 +99,8 @@ public class AWSEC2ComputeService extends EC2ComputeService {
RunScriptOnNode.Factory runScriptOnNodeFactory, InitAdminAccess initAdminAccess, RunScriptOnNode.Factory runScriptOnNodeFactory, InitAdminAccess initAdminAccess,
PersistNodeCredentials persistNodeCredentials, Timeouts timeouts, PersistNodeCredentials persistNodeCredentials, Timeouts timeouts,
@Named(Constants.PROPERTY_USER_THREADS) ExecutorService executor, AWSEC2Client ec2Client, @Named(Constants.PROPERTY_USER_THREADS) ExecutorService executor, AWSEC2Client ec2Client,
Cache<RegionAndName, KeyPair> credentialsMap, @Named("SECURITY") Cache<RegionAndName, String> securityGroupMap, Cache<RegionAndName, KeyPair> credentialsMap,
@Named("SECURITY") Cache<RegionAndName, String> securityGroupMap,
@Named("PLACEMENT") Cache<RegionAndName, String> placementGroupMap, @Named("PLACEMENT") Cache<RegionAndName, String> placementGroupMap,
@Named("DELETED") Predicate<PlacementGroup> placementGroupDeleted) { @Named("DELETED") Predicate<PlacementGroup> placementGroupDeleted) {
super(context, credentialStore, images, sizes, locations, listNodesStrategy, getNodeMetadataStrategy, super(context, credentialStore, images, sizes, locations, listNodesStrategy, getNodeMetadataStrategy,
@ -104,6 +113,50 @@ public class AWSEC2ComputeService extends EC2ComputeService {
this.placementGroupDeleted = placementGroupDeleted; this.placementGroupDeleted = placementGroupDeleted;
} }
@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, template);
nodes = addUserMetadataFromTemplateOptionsToNodes(template, nodes);
}
return nodes;
}
protected void addTagsToNodesFromUserMetadataInTemplate(Set<? extends NodeMetadata> nodes, final Template template) {
String region = AWSUtils.getRegionFromLocationOrNull(template.getLocation());
ec2Client.getTagServices().createTagsInRegion(region, transform(nodes, new Function<NodeMetadata, String>() {
@Override
public String apply(NodeMetadata arg0) {
return arg0.getProviderId();
}
}), template.getOptions().getUserMetadata());
}
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,
Set<? extends NodeMetadata> nodes) {
nodes = ImmutableSet.copyOf(Iterables.transform(nodes, new Function<NodeMetadata, NodeMetadata>() {
@Override
public NodeMetadata apply(NodeMetadata arg0) {
return NodeMetadataBuilder.fromNodeMetadata(arg0).userMetadata(template.getOptions().getUserMetadata())
.build();
}
}));
return nodes;
}
@VisibleForTesting @VisibleForTesting
void deletePlacementGroup(String region, String group) { void deletePlacementGroup(String region, String group) {
Preconditions2.checkNotEmpty(group, "group"); Preconditions2.checkNotEmpty(group, "group");

View File

@ -23,16 +23,16 @@ import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.base.Preconditions.checkState; import static com.google.common.base.Preconditions.checkState;
import java.util.Arrays; import java.util.Arrays;
import java.util.Map;
import java.util.Set; import java.util.Set;
import org.jclouds.javax.annotation.Nullable;
import org.jclouds.aws.ec2.options.RequestSpotInstancesOptions; import org.jclouds.aws.ec2.options.RequestSpotInstancesOptions;
import org.jclouds.compute.options.TemplateOptions; import org.jclouds.compute.options.TemplateOptions;
import org.jclouds.domain.Credentials; import org.jclouds.domain.Credentials;
import org.jclouds.ec2.compute.options.EC2TemplateOptions; import org.jclouds.ec2.compute.options.EC2TemplateOptions;
import org.jclouds.ec2.domain.BlockDeviceMapping; import org.jclouds.ec2.domain.BlockDeviceMapping;
import org.jclouds.io.Payload; import org.jclouds.io.Payload;
import org.jclouds.javax.annotation.Nullable;
import org.jclouds.scriptbuilder.domain.Statement; import org.jclouds.scriptbuilder.domain.Statement;
import org.jclouds.util.Preconditions2; import org.jclouds.util.Preconditions2;
@ -40,11 +40,11 @@ import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Iterables; import com.google.common.collect.Iterables;
/** /**
* Contains options supported in the {@code ComputeService#runNode} operation on the "ec2" provider. * Contains options supported in the {@code ComputeService#runNode} operation on
* <h2> * the "ec2" provider. <h2>
* Usage</h2> The recommended way to instantiate a AWSEC2TemplateOptions object is to statically * Usage</h2> The recommended way to instantiate a AWSEC2TemplateOptions object
* import AWSEC2TemplateOptions.* and invoke a static creation method followed by an instance * is to statically import AWSEC2TemplateOptions.* and invoke a static creation
* mutator (if needed): * method followed by an instance mutator (if needed):
* <p/> * <p/>
* <code> * <code>
* import static org.jclouds.aws.ec2.compute.options.AWSEC2TemplateOptions.Builder.*; * import static org.jclouds.aws.ec2.compute.options.AWSEC2TemplateOptions.Builder.*;
@ -175,10 +175,6 @@ public class AWSEC2TemplateOptions extends EC2TemplateOptions implements Cloneab
return groupIds; return groupIds;
} }
public void setGroupIds(Set<String> groupIds) {
this.groupIds = groupIds;
}
public static class Builder { public static class Builder {
/** /**
@ -344,14 +340,6 @@ public class AWSEC2TemplateOptions extends EC2TemplateOptions implements Cloneab
return options.authorizePublicKey(rsaKey); return options.authorizePublicKey(rsaKey);
} }
/**
* @see TemplateOptions#withDetails
*/
public static AWSEC2TemplateOptions withDetails() {
AWSEC2TemplateOptions options = new AWSEC2TemplateOptions();
return options.withMetadata();
}
/** /**
* @see TemplateOptions#spotPrice * @see TemplateOptions#spotPrice
*/ */
@ -375,6 +363,22 @@ public class AWSEC2TemplateOptions extends EC2TemplateOptions implements Cloneab
AWSEC2TemplateOptions options = new AWSEC2TemplateOptions(); AWSEC2TemplateOptions options = new AWSEC2TemplateOptions();
return options.spotOptions(spotOptions); return options.spotOptions(spotOptions);
} }
/**
* @see TemplateOptions#userMetadata(Map)
*/
public static AWSEC2TemplateOptions userMetadata(Map<String, String> userMetadata) {
AWSEC2TemplateOptions options = new AWSEC2TemplateOptions();
return AWSEC2TemplateOptions.class.cast(options.userMetadata(userMetadata));
}
/**
* @see TemplateOptions#userMetadata(String, String)
*/
public static AWSEC2TemplateOptions userMetadata(String key, String value) {
AWSEC2TemplateOptions options = new AWSEC2TemplateOptions();
return AWSEC2TemplateOptions.class.cast(options.userMetadata(key, value));
}
} }
// methods that only facilitate returning the correct object type // methods that only facilitate returning the correct object type
@ -387,6 +391,22 @@ public class AWSEC2TemplateOptions extends EC2TemplateOptions implements Cloneab
return AWSEC2TemplateOptions.class.cast(super.blockDeviceMappings(blockDeviceMappings)); return AWSEC2TemplateOptions.class.cast(super.blockDeviceMappings(blockDeviceMappings));
} }
/**
* {@inheritDoc}
*/
@Override
public AWSEC2TemplateOptions userMetadata(Map<String, String> userMetadata) {
return AWSEC2TemplateOptions.class.cast(super.userMetadata(userMetadata));
}
/**
* {@inheritDoc}
*/
@Override
public AWSEC2TemplateOptions userMetadata(String key, String value) {
return AWSEC2TemplateOptions.class.cast(super.userMetadata(key, value));
}
/** /**
* {@inheritDoc} * {@inheritDoc}
*/ */
@ -530,14 +550,6 @@ public class AWSEC2TemplateOptions extends EC2TemplateOptions implements Cloneab
return AWSEC2TemplateOptions.class.cast(super.runScript(script)); return AWSEC2TemplateOptions.class.cast(super.runScript(script));
} }
/**
* {@inheritDoc}
*/
@Override
public AWSEC2TemplateOptions withMetadata() {
return AWSEC2TemplateOptions.class.cast(super.withMetadata());
}
/** /**
* {@inheritDoc} * {@inheritDoc}
*/ */
@ -587,7 +599,8 @@ public class AWSEC2TemplateOptions extends EC2TemplateOptions implements Cloneab
} }
/** /**
* @return placementGroup to use when running the instance or null, to generate a placementGroup. * @return placementGroup to use when running the instance or null, to
* generate a placementGroup.
*/ */
public String getPlacementGroup() { public String getPlacementGroup() {
return placementGroup; return placementGroup;

View File

@ -66,4 +66,8 @@ public class AWSRunningInstanceToNodeMetadata extends RunningInstanceToNodeMetad
builder.credentials(creds); builder.credentials(creds);
} }
@Override
protected NodeMetadataBuilder buildInstance(RunningInstance instance, NodeMetadataBuilder builder) {
return super.buildInstance(instance, builder).userMetadata(AWSRunningInstance.class.cast(instance).getTags());
}
} }

View File

@ -19,6 +19,7 @@
package org.jclouds.aws.ec2.compute.strategy; package org.jclouds.aws.ec2.compute.strategy;
import static com.google.common.base.Preconditions.checkNotNull; import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.collect.Iterables.transform;
import java.util.Map; import java.util.Map;
@ -50,7 +51,6 @@ import org.jclouds.logging.Logger;
import com.google.common.annotations.VisibleForTesting; import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Function; import com.google.common.base.Function;
import com.google.common.cache.Cache; import com.google.common.cache.Cache;
import com.google.common.collect.Iterables;
/** /**
* *
@ -72,8 +72,7 @@ public class AWSEC2CreateNodesInGroupThenAddToSet extends EC2CreateNodesInGroupT
AWSEC2Client client, AWSEC2Client client,
Provider<TemplateBuilder> templateBuilderProvider, Provider<TemplateBuilder> templateBuilderProvider,
CreateKeyPairPlacementAndSecurityGroupsAsNeededAndReturnRunOptions createKeyPairAndSecurityGroupsAsNeededAndReturncustomize, CreateKeyPairPlacementAndSecurityGroupsAsNeededAndReturnRunOptions createKeyPairAndSecurityGroupsAsNeededAndReturncustomize,
AWSEC2InstancePresent instancePresent, AWSEC2InstancePresent instancePresent, Function<RunningInstance, NodeMetadata> runningInstanceToNodeMetadata,
Function<RunningInstance, NodeMetadata> runningInstanceToNodeMetadata,
Cache<RunningInstance, Credentials> instanceToCredentials, Map<String, Credentials> credentialStore, Cache<RunningInstance, Credentials> instanceToCredentials, Map<String, Credentials> credentialStore,
ComputeUtils utils, SpotInstanceRequestToAWSRunningInstance spotConverter) { ComputeUtils utils, SpotInstanceRequestToAWSRunningInstance spotConverter) {
super(client, templateBuilderProvider, createKeyPairAndSecurityGroupsAsNeededAndReturncustomize, instancePresent, super(client, templateBuilderProvider, createKeyPairAndSecurityGroupsAsNeededAndReturncustomize, instancePresent,
@ -93,14 +92,34 @@ public class AWSEC2CreateNodesInGroupThenAddToSet extends EC2CreateNodesInGroupT
logger.debug(">> requesting %d spot instances region(%s) price(%f) spec(%s) options(%s)", count, region, logger.debug(">> requesting %d spot instances region(%s) price(%f) spec(%s) options(%s)", count, region,
spotPrice, spec, options); spotPrice, spec, options);
return Iterables.transform(client.getSpotInstanceServices().requestSpotInstancesInRegion(region, spotPrice, return addTagsToInstancesInRegion(
count, spec, options), spotConverter); template.getOptions().getUserMetadata(),
transform(
client.getSpotInstanceServices().requestSpotInstancesInRegion(region, spotPrice, count, spec,
options), spotConverter), region);
} else { } else {
return super.createNodesInRegionAndZone(region, zone, count, template, instanceOptions); return addTagsToInstancesInRegion(template.getOptions().getUserMetadata(),
super.createNodesInRegionAndZone(region, zone, count, template, instanceOptions), region);
} }
} }
public Iterable<? extends RunningInstance> addTagsToInstancesInRegion(Map<String, String> metadata,
Iterable<? extends RunningInstance> iterable, String region) {
if (metadata.size() > 0) {
client.getTagServices().createTagsInRegion(region,
transform(iterable, new Function<RunningInstance, String>() {
@Override
public String apply(RunningInstance arg0) {
return arg0.getId();
}
}), metadata);
}
return iterable;
}
private Float getSpotPriceOrNull(TemplateOptions options) { private Float getSpotPriceOrNull(TemplateOptions options) {
return options instanceof AWSEC2TemplateOptions ? AWSEC2TemplateOptions.class.cast(options).getSpotPrice() : null; return options instanceof AWSEC2TemplateOptions ? AWSEC2TemplateOptions.class.cast(options).getSpotPrice() : null;
} }

View File

@ -56,6 +56,18 @@ public class AWSRunningInstance extends RunningInstance {
private String spotInstanceRequestId; private String spotInstanceRequestId;
private String vpcId; private String vpcId;
private Map<String, String> securityGroupIdToNames = Maps.newLinkedHashMap(); 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 && value != null)
this.tags.put(key, value);
return this;
}
public Builder securityGroupIdToNames(Map<String, String> securityGroupIdToNames) { public Builder securityGroupIdToNames(Map<String, String> securityGroupIdToNames) {
this.securityGroupIdToNames = ImmutableMap.copyOf(checkNotNull(securityGroupIdToNames, this.securityGroupIdToNames = ImmutableMap.copyOf(checkNotNull(securityGroupIdToNames,
@ -231,7 +243,7 @@ public class AWSRunningInstance extends RunningInstance {
instanceState, instanceType, ipAddress, kernelId, keyName, launchTime, availabilityZone, instanceState, instanceType, ipAddress, kernelId, keyName, launchTime, availabilityZone,
virtualizationType, platform, privateDnsName, privateIpAddress, ramdiskId, reason, rootDeviceType, virtualizationType, platform, privateDnsName, privateIpAddress, ramdiskId, reason, rootDeviceType,
rootDeviceName, ebsBlockDevices, monitoringState, placementGroup, productCodes, subnetId, rootDeviceName, ebsBlockDevices, monitoringState, placementGroup, productCodes, subnetId,
spotInstanceRequestId, vpcId); spotInstanceRequestId, vpcId, tags);
} }
} }
@ -247,6 +259,7 @@ public class AWSRunningInstance extends RunningInstance {
@Nullable @Nullable
private final String vpcId; private final String vpcId;
private final Map<String, String> securityGroupIdToNames; private final Map<String, String> securityGroupIdToNames;
private final Map<String, String> tags;
protected AWSRunningInstance(String region, Map<String, String> securityGroupIdToNames, String amiLaunchIndex, protected AWSRunningInstance(String region, Map<String, String> securityGroupIdToNames, String amiLaunchIndex,
String dnsName, String imageId, String instanceId, InstanceState instanceState, String instanceType, String dnsName, String imageId, String instanceId, InstanceState instanceState, String instanceType,
@ -254,7 +267,7 @@ public class AWSRunningInstance extends RunningInstance {
String virtualizationType, String platform, String privateDnsName, String privateIpAddress, String ramdiskId, String virtualizationType, String platform, String privateDnsName, String privateIpAddress, String ramdiskId,
String reason, RootDeviceType rootDeviceType, String rootDeviceName, Map<String, BlockDevice> ebsBlockDevices, String reason, RootDeviceType rootDeviceType, String rootDeviceName, Map<String, BlockDevice> ebsBlockDevices,
MonitoringState monitoringState, String placementGroup, Iterable<String> productCodes, String subnetId, MonitoringState monitoringState, String placementGroup, Iterable<String> productCodes, String subnetId,
String spotInstanceRequestId, String vpcId) { String spotInstanceRequestId, String vpcId, Map<String, String> tags) {
super(region, securityGroupIdToNames.values(), amiLaunchIndex, dnsName, imageId, instanceId, instanceState, super(region, securityGroupIdToNames.values(), amiLaunchIndex, dnsName, imageId, instanceId, instanceState,
instanceType, ipAddress, kernelId, keyName, launchTime, availabilityZone, virtualizationType, platform, instanceType, ipAddress, kernelId, keyName, launchTime, availabilityZone, virtualizationType, platform,
privateDnsName, privateIpAddress, ramdiskId, reason, rootDeviceType, rootDeviceName, ebsBlockDevices); privateDnsName, privateIpAddress, ramdiskId, reason, rootDeviceType, rootDeviceName, ebsBlockDevices);
@ -266,6 +279,7 @@ public class AWSRunningInstance extends RunningInstance {
this.vpcId = vpcId; this.vpcId = vpcId;
this.securityGroupIdToNames = ImmutableMap.<String, String> copyOf(checkNotNull(securityGroupIdToNames, this.securityGroupIdToNames = ImmutableMap.<String, String> copyOf(checkNotNull(securityGroupIdToNames,
"securityGroupIdToNames")); "securityGroupIdToNames"));
this.tags = ImmutableMap.<String, String> copyOf(checkNotNull(tags, "tags"));
} }
public Map<String, String> getSecurityGroupIdToNames() { public Map<String, String> getSecurityGroupIdToNames() {
@ -317,6 +331,13 @@ public class AWSRunningInstance extends RunningInstance {
return subnetId; return subnetId;
} }
/**
* tags that are present in the instance
*/
public Map<String, String> getTags() {
return tags;
}
@Override @Override
public int hashCode() { public int hashCode() {
final int prime = 31; final int prime = 31;
@ -326,6 +347,7 @@ public class AWSRunningInstance extends RunningInstance {
result = prime * result + ((spotInstanceRequestId == null) ? 0 : spotInstanceRequestId.hashCode()); result = prime * result + ((spotInstanceRequestId == null) ? 0 : spotInstanceRequestId.hashCode());
result = prime * result + ((subnetId == null) ? 0 : subnetId.hashCode()); result = prime * result + ((subnetId == null) ? 0 : subnetId.hashCode());
result = prime * result + ((vpcId == null) ? 0 : vpcId.hashCode()); result = prime * result + ((vpcId == null) ? 0 : vpcId.hashCode());
result = prime * result + ((tags == null) ? 0 : tags.hashCode());
return result; return result;
} }
@ -363,6 +385,11 @@ public class AWSRunningInstance extends RunningInstance {
return false; return false;
} else if (!vpcId.equals(other.vpcId)) } else if (!vpcId.equals(other.vpcId))
return false; return false;
if (tags == null) {
if (other.tags != null)
return false;
} else if (!tags.equals(other.tags))
return false;
return true; return true;
} }
@ -375,7 +402,8 @@ public class AWSRunningInstance extends RunningInstance {
+ ", platform=" + platform + ", launchTime=" + launchTime + ", rootDeviceName=" + rootDeviceName + ", platform=" + platform + ", launchTime=" + launchTime + ", rootDeviceName=" + rootDeviceName
+ ", rootDeviceType=" + rootDeviceType + ", ebsBlockDevices=" + ebsBlockDevices + ", monitoringState=" + ", rootDeviceType=" + rootDeviceType + ", ebsBlockDevices=" + ebsBlockDevices + ", monitoringState="
+ monitoringState + ", placementGroup=" + placementGroup + ", productCodes=" + productCodes + monitoringState + ", placementGroup=" + placementGroup + ", productCodes=" + productCodes
+ ", spotInstanceRequestId=" + spotInstanceRequestId + ", subnetId=" + subnetId + ", vpcId=" + vpcId + "]"; + ", spotInstanceRequestId=" + spotInstanceRequestId + ", subnetId=" + subnetId + ", vpcId=" + vpcId
+ ", tags=" + tags + "]";
} }
} }

View File

@ -18,12 +18,16 @@
*/ */
package org.jclouds.aws.ec2.domain; package org.jclouds.aws.ec2.domain;
import java.util.Date; import static com.google.common.base.Preconditions.checkNotNull;
import java.util.Date;
import java.util.Map;
import com.google.common.base.CaseFormat;
import org.jclouds.javax.annotation.Nullable; import org.jclouds.javax.annotation.Nullable;
import static com.google.common.base.Preconditions.checkNotNull; import com.google.common.base.CaseFormat;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Maps;
/** /**
* *
@ -51,6 +55,7 @@ public class SpotInstanceRequest implements Comparable<SpotInstanceRequest> {
private Type type; private Type type;
private Date validFrom; private Date validFrom;
private Date validUntil; private Date validUntil;
private Map<String, String> tags = Maps.newLinkedHashMap();
public Builder clear() { public Builder clear() {
this.region = null; this.region = null;
@ -69,6 +74,7 @@ public class SpotInstanceRequest implements Comparable<SpotInstanceRequest> {
this.type = null; this.type = null;
this.validFrom = null; this.validFrom = null;
this.validUntil = null; this.validUntil = null;
tags = Maps.newLinkedHashMap();
return this; return this;
} }
@ -77,6 +83,16 @@ public class SpotInstanceRequest implements Comparable<SpotInstanceRequest> {
return this; return this;
} }
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 && value != null)
this.tags.put(key, value);
return this;
}
public Builder availabilityZoneGroup(String availabilityZoneGroup) { public Builder availabilityZoneGroup(String availabilityZoneGroup) {
this.availabilityZoneGroup = availabilityZoneGroup; this.availabilityZoneGroup = availabilityZoneGroup;
return this; return this;
@ -155,7 +171,7 @@ public class SpotInstanceRequest implements Comparable<SpotInstanceRequest> {
public SpotInstanceRequest build() { public SpotInstanceRequest build() {
return new SpotInstanceRequest(region, availabilityZoneGroup, launchedAvailabilityZone, createTime, faultCode, return new SpotInstanceRequest(region, availabilityZoneGroup, launchedAvailabilityZone, createTime, faultCode,
faultMessage, instanceId, launchGroup, launchSpecification, productDescription, id, spotPrice, state, faultMessage, instanceId, launchGroup, launchSpecification, productDescription, id, spotPrice, state,
type, validFrom, validUntil); type, validFrom, validUntil, tags);
} }
} }
@ -217,11 +233,12 @@ public class SpotInstanceRequest implements Comparable<SpotInstanceRequest> {
private final Type type; private final Type type;
private final Date validFrom; private final Date validFrom;
private final Date validUntil; private final Date validUntil;
private final Map<String, String> tags;
public SpotInstanceRequest(String region, String availabilityZoneGroup, @Nullable String launchedAvailabilityZone, public SpotInstanceRequest(String region, String availabilityZoneGroup, @Nullable String launchedAvailabilityZone,
Date createTime, String faultCode, String faultMessage, String instanceId, String launchGroup, Date createTime, String faultCode, String faultMessage, String instanceId, String launchGroup,
LaunchSpecification launchSpecification, String productDescription, String id, float spotPrice, State state, LaunchSpecification launchSpecification, String productDescription, String id, float spotPrice, State state,
Type type, Date validFrom, Date validUntil) { Type type, Date validFrom, Date validUntil, Map<String, String> tags) {
this.region = checkNotNull(region, "region"); this.region = checkNotNull(region, "region");
this.availabilityZoneGroup = availabilityZoneGroup; this.availabilityZoneGroup = availabilityZoneGroup;
this.launchedAvailabilityZone = launchedAvailabilityZone; this.launchedAvailabilityZone = launchedAvailabilityZone;
@ -238,6 +255,7 @@ public class SpotInstanceRequest implements Comparable<SpotInstanceRequest> {
this.type = checkNotNull(type, "type"); this.type = checkNotNull(type, "type");
this.validFrom = validFrom; this.validFrom = validFrom;
this.validUntil = validUntil; this.validUntil = validUntil;
this.tags = ImmutableMap.<String, String> copyOf(checkNotNull(tags, "tags"));
} }
/** /**
@ -307,6 +325,13 @@ public class SpotInstanceRequest implements Comparable<SpotInstanceRequest> {
return validUntil; return validUntil;
} }
/**
* tags that are present in the instance
*/
public Map<String, String> getTags() {
return tags;
}
@Override @Override
public int hashCode() { public int hashCode() {
final int prime = 31; final int prime = 31;
@ -327,6 +352,7 @@ public class SpotInstanceRequest implements Comparable<SpotInstanceRequest> {
result = prime * result + ((type == null) ? 0 : type.hashCode()); result = prime * result + ((type == null) ? 0 : type.hashCode());
result = prime * result + ((validFrom == null) ? 0 : validFrom.hashCode()); result = prime * result + ((validFrom == null) ? 0 : validFrom.hashCode());
result = prime * result + ((validUntil == null) ? 0 : validUntil.hashCode()); result = prime * result + ((validUntil == null) ? 0 : validUntil.hashCode());
result = prime * result + ((tags == null) ? 0 : tags.hashCode());
return result; return result;
} }
@ -410,6 +436,11 @@ public class SpotInstanceRequest implements Comparable<SpotInstanceRequest> {
return false; return false;
} else if (!validUntil.equals(other.validUntil)) } else if (!validUntil.equals(other.validUntil))
return false; return false;
if (tags == null) {
if (other.tags != null)
return false;
} else if (!tags.equals(other.tags))
return false;
return true; return true;
} }
@ -420,7 +451,7 @@ public class SpotInstanceRequest implements Comparable<SpotInstanceRequest> {
+ faultMessage + ", instanceId=" + instanceId + ", launchGroup=" + launchGroup + ", launchSpecification=" + faultMessage + ", instanceId=" + instanceId + ", launchGroup=" + launchGroup + ", launchSpecification="
+ launchSpecification + ", productDescription=" + productDescription + ", id=" + id + ", spotPrice=" + launchSpecification + ", productDescription=" + productDescription + ", id=" + id + ", spotPrice="
+ spotPrice + ", state=" + state + ", type=" + type + ", validFrom=" + validFrom + ", validUntil=" + spotPrice + ", state=" + state + ", type=" + type + ", validFrom=" + validFrom + ", validUntil="
+ validUntil + "]"; + validUntil + ", tags=" + tags + "]";
} }
@Override @Override

View File

@ -45,6 +45,7 @@ public class SpotInstanceRequestToAWSRunningInstance implements Function<SpotIns
builder.instanceId(request.getId()); builder.instanceId(request.getId());
builder.instanceState(InstanceState.PENDING); builder.instanceState(InstanceState.PENDING);
builder.region(request.getRegion()); builder.region(request.getRegion());
builder.tags(request.getTags());
LaunchSpecification spec = request.getLaunchSpecification(); LaunchSpecification spec = request.getLaunchSpecification();
builder.availabilityZone(spec.getAvailabilityZone()); builder.availabilityZone(spec.getAvailabilityZone());
// TODO convert // TODO convert

View File

@ -18,7 +18,7 @@
*/ */
package org.jclouds.aws.ec2.util; package org.jclouds.aws.ec2.util;
import static com.google.common.base.Preconditions.*; import static com.google.common.base.Preconditions.checkNotNull;
import java.util.Map; import java.util.Map;
@ -34,10 +34,7 @@ import com.google.common.collect.Sets;
*/ */
public class TagFilters { public class TagFilters {
public static enum FilterName { public static enum FilterName {
KEY, KEY, RESOURCE_ID, RESOURCE_TYPE, VALUE;
RESOURCE_ID,
RESOURCE_TYPE,
VALUE;
public String value() { public String value() {
return CaseFormat.UPPER_UNDERSCORE.to(CaseFormat.LOWER_HYPHEN, name()); return CaseFormat.UPPER_UNDERSCORE.to(CaseFormat.LOWER_HYPHEN, name());
@ -58,22 +55,7 @@ public class TagFilters {
} }
public static enum ResourceType { public static enum ResourceType {
CUSTOMER_GATEWAY, CUSTOMER_GATEWAY, DHCP_OPTIONS, IMAGE, INSTANCE, INTERNET_GATEWAY, NETWORK_ACL, RESERVED_INSTANCES, ROUTE_TABLE, SECURITY_GROUP, SNAPSHOT, SPOT_INSTANCES_REQUEST, SUBNET, VOLUME, VPC, VPN_CONNECTION, VPN_GATEWAY;
DHCP_OPTIONS,
IMAGE,
INSTANCE,
INTERNET_GATEWAY,
NETWORK_ACL,
RESERVED_INSTANCES,
ROUTE_TABLE,
SECURITY_GROUP,
SNAPSHOT,
SPOT_INSTANCES_REQUEST,
SUBNET,
VOLUME,
VPC,
VPN_CONNECTION,
VPN_GATEWAY;
public String value() { public String value() {
return CaseFormat.UPPER_UNDERSCORE.to(CaseFormat.LOWER_HYPHEN, name()); return CaseFormat.UPPER_UNDERSCORE.to(CaseFormat.LOWER_HYPHEN, name());
@ -96,7 +78,7 @@ public class TagFilters {
protected final Map<FilterName, Iterable<?>> map; protected final Map<FilterName, Iterable<?>> map;
protected TagFilters() { protected TagFilters() {
map = Maps.<FilterName, Iterable<?>>newLinkedHashMap(); map = Maps.<FilterName, Iterable<?>> newLinkedHashMap();
} }
public static TagFilters filters() { public static TagFilters filters() {
@ -117,13 +99,13 @@ public class TagFilters {
return this; return this;
} }
public TagFilters keys(String...keys) { public TagFilters keys(String... keys) {
put(FilterName.KEY, ImmutableSet.<String>copyOf(keys)); put(FilterName.KEY, ImmutableSet.<String> copyOf(keys));
return this; return this;
} }
public TagFilters keys(Iterable<String> keys) { public TagFilters keys(Iterable<String> keys) {
putAll(FilterName.KEY, ImmutableSet.<String>copyOf(keys)); putAll(FilterName.KEY, ImmutableSet.<String> copyOf(keys));
return this; return this;
} }
@ -132,13 +114,13 @@ public class TagFilters {
return this; return this;
} }
public TagFilters values(String...values) { public TagFilters values(String... values) {
putAll(FilterName.VALUE, ImmutableSet.<String>copyOf(values)); putAll(FilterName.VALUE, ImmutableSet.<String> copyOf(values));
return this; return this;
} }
public TagFilters values(Iterable<String> values) { public TagFilters values(Iterable<String> values) {
putAll(FilterName.VALUE, ImmutableSet.<String>copyOf(values)); putAll(FilterName.VALUE, ImmutableSet.<String> copyOf(values));
return this; return this;
} }
@ -186,27 +168,27 @@ public class TagFilters {
return key(key).values(values); return key(key).values(values);
} }
public TagFilters keyValueSet(String key, String...values) { public TagFilters keyValueSet(String key, String... values) {
return key(key).values(values); return key(key).values(values);
} }
public TagFilters anyKey() { public TagFilters anyKey() {
putAll(FilterName.KEY, ImmutableSet.<String>of()); putAll(FilterName.KEY, ImmutableSet.<String> of());
return this; return this;
} }
public TagFilters anyValue() { public TagFilters anyValue() {
putAll(FilterName.VALUE, ImmutableSet.<String>of()); putAll(FilterName.VALUE, ImmutableSet.<String> of());
return this; return this;
} }
public TagFilters anyResourceId() { public TagFilters anyResourceId() {
putAll(FilterName.RESOURCE_TYPE, ImmutableSet.<String>of()); putAll(FilterName.RESOURCE_TYPE, ImmutableSet.<String> of());
return this; return this;
} }
public TagFilters anyResourceType() { public TagFilters anyResourceType() {
putAll(FilterName.RESOURCE_TYPE, ImmutableSet.<ResourceType>of()); putAll(FilterName.RESOURCE_TYPE, ImmutableSet.<ResourceType> of());
return this; return this;
} }
@ -301,7 +283,8 @@ public class TagFilters {
private void putAll(FilterName key, Iterable<?> values) { private void putAll(FilterName key, Iterable<?> values) {
if (values == null || Iterables.isEmpty(values)) { if (values == null || Iterables.isEmpty(values)) {
// If we add an empty or null set of values, replace the value in the map entirely // If we add an empty or null set of values, replace the value in the
// map entirely
map.put(key, ImmutableSet.of()); map.put(key, ImmutableSet.of());
} else { } else {
// Add the values, to a new set if required // Add the values, to a new set if required

View File

@ -18,6 +18,9 @@
*/ */
package org.jclouds.aws.ec2.xml; 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 java.util.Set;
import javax.inject.Inject; import javax.inject.Inject;
@ -27,6 +30,8 @@ import org.jclouds.date.DateService;
import org.jclouds.ec2.domain.Reservation; import org.jclouds.ec2.domain.Reservation;
import org.jclouds.ec2.domain.RunningInstance; import org.jclouds.ec2.domain.RunningInstance;
import org.jclouds.location.Region; import org.jclouds.location.Region;
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import com.google.common.collect.Sets; import com.google.common.collect.Sets;
import com.google.inject.Provider; import com.google.inject.Provider;
@ -42,6 +47,9 @@ import com.google.inject.Provider;
public class AWSDescribeInstancesResponseHandler extends public class AWSDescribeInstancesResponseHandler extends
BaseAWSReservationHandler<Set<Reservation<? extends RunningInstance>>> { BaseAWSReservationHandler<Set<Reservation<? extends RunningInstance>>> {
private Set<Reservation<? extends RunningInstance>> reservations = Sets.newLinkedHashSet(); private Set<Reservation<? extends RunningInstance>> reservations = Sets.newLinkedHashSet();
private boolean inTagSet;
private String key;
private String value;
@Inject @Inject
AWSDescribeInstancesResponseHandler(DateService dateService, @Region String defaultRegion, AWSDescribeInstancesResponseHandler(DateService dateService, @Region String defaultRegion,
@ -49,6 +57,28 @@ public class AWSDescribeInstancesResponseHandler extends
super(dateService, defaultRegion, builderProvider); super(dateService, defaultRegion, builderProvider);
} }
@Override
public void startElement(String uri, String localName, String qName, Attributes attrs) throws SAXException {
super.startElement(uri, localName, qName, attrs);
if (equalsOrSuffix(qName, "tagSet")) {
inTagSet = true;
}
}
@Override
public void endElement(String uri, String name, String qName) {
if (equalsOrSuffix(qName, "tagSet")) {
inTagSet = false;
} else if (inTagSet) {
if (equalsOrSuffix(qName, "key")) {
key = currentOrNull(currentText);
} else if (equalsOrSuffix(qName, "value")) {
value = currentOrNull(currentText);
}
}
super.endElement(uri, name, qName);
}
@Override @Override
public Set<Reservation<? extends RunningInstance>> getResult() { public Set<Reservation<? extends RunningInstance>> getResult() {
return reservations; return reservations;
@ -62,6 +92,10 @@ public class AWSDescribeInstancesResponseHandler extends
protected void inItem() { protected void inItem() {
if (endOfReservationItem()) { if (endOfReservationItem()) {
reservations.add(super.newReservation()); reservations.add(super.newReservation());
} else if (inTagSet) {
builder.tag(key, value);
key = null;
value = null;
} else { } else {
super.inItem(); super.inItem();
} }

View File

@ -18,6 +18,9 @@
*/ */
package org.jclouds.aws.ec2.xml; package org.jclouds.aws.ec2.xml;
import static org.jclouds.util.SaxUtils.currentOrNull;
import static org.jclouds.util.SaxUtils.equalsOrSuffix;
import javax.inject.Inject; import javax.inject.Inject;
import org.jclouds.aws.ec2.domain.SpotInstanceRequest; import org.jclouds.aws.ec2.domain.SpotInstanceRequest;
@ -40,6 +43,9 @@ public class SpotInstanceHandler extends ParseSax.HandlerForGeneratedRequestWith
protected final Builder builder; protected final Builder builder;
protected boolean inLaunchSpecification; protected boolean inLaunchSpecification;
protected final LaunchSpecificationHandler launchSpecificationHandler; protected final LaunchSpecificationHandler launchSpecificationHandler;
private boolean inTagSet;
private String key;
private String value;
@Inject @Inject
public SpotInstanceHandler(DateService dateService, @Region String defaultRegion, public SpotInstanceHandler(DateService dateService, @Region String defaultRegion,
@ -50,11 +56,6 @@ public class SpotInstanceHandler extends ParseSax.HandlerForGeneratedRequestWith
this.builder = builder; this.builder = builder;
} }
protected String currentOrNull() {
String returnVal = currentText.toString().trim();
return returnVal.equals("") ? null : returnVal;
}
public SpotInstanceRequest getResult() { public SpotInstanceRequest getResult() {
try { try {
String region = getRequest() != null ? AWSUtils.findRegionInArgsOrNull(getRequest()) : null; String region = getRequest() != null ? AWSUtils.findRegionInArgsOrNull(getRequest()) : null;
@ -67,52 +68,67 @@ public class SpotInstanceHandler extends ParseSax.HandlerForGeneratedRequestWith
} }
public void startElement(String uri, String name, String qName, Attributes attrs) { public void startElement(String uri, String name, String qName, Attributes attrs) {
if (qName.equals("launchSpecification")) { if (equalsOrSuffix(qName, "launchSpecification")) {
inLaunchSpecification = true; inLaunchSpecification = true;
} else if (equalsOrSuffix(qName, "tagSet")) {
inTagSet = true;
} }
if (inLaunchSpecification) if (inLaunchSpecification)
launchSpecificationHandler.startElement(uri, name, qName, attrs); launchSpecificationHandler.startElement(uri, name, qName, attrs);
} }
public void endElement(String uri, String name, String qName) { public void endElement(String uri, String name, String qName) {
if (equalsOrSuffix(qName, "tagSet")) {
inTagSet = false;
} else if (inTagSet) {
if (equalsOrSuffix(qName, "key")) {
key = currentOrNull(currentText);
} else if (equalsOrSuffix(qName, "value")) {
value = currentOrNull(currentText);
}
}
if (qName.equals("launchSpecification")) { if (qName.equals("launchSpecification")) {
inLaunchSpecification = false; inLaunchSpecification = false;
builder.launchSpecification(launchSpecificationHandler.getResult()); builder.launchSpecification(launchSpecificationHandler.getResult());
} else if (qName.equals("item") && inTagSet) {
builder.tag(key, value);
key = null;
value = null;
} }
if (inLaunchSpecification) { if (inLaunchSpecification) {
launchSpecificationHandler.endElement(uri, name, qName); launchSpecificationHandler.endElement(uri, name, qName);
} else if (qName.equals("spotInstanceRequestId")) { } else if (qName.equals("spotInstanceRequestId")) {
builder.id(currentOrNull()); builder.id(currentOrNull(currentText));
} else if (qName.equals("instanceId")) { } else if (qName.equals("instanceId")) {
builder.instanceId(currentOrNull()); builder.instanceId(currentOrNull(currentText));
} else if (qName.equals("launchedAvailabilityZone")) { } else if (qName.equals("launchedAvailabilityZone")) {
builder.launchedAvailabilityZone(currentOrNull()); builder.launchedAvailabilityZone(currentOrNull(currentText));
} else if (qName.equals("availabilityZoneGroup")) { } else if (qName.equals("availabilityZoneGroup")) {
builder.availabilityZoneGroup(currentOrNull()); builder.availabilityZoneGroup(currentOrNull(currentText));
} else if (qName.equals("launchGroup")) { } else if (qName.equals("launchGroup")) {
builder.launchGroup(currentOrNull()); builder.launchGroup(currentOrNull(currentText));
} else if (qName.equals("code")) { } else if (qName.equals("code")) {
builder.faultCode(currentOrNull()); builder.faultCode(currentOrNull(currentText));
} else if (qName.equals("message")) { } else if (qName.equals("message")) {
builder.faultMessage(currentOrNull()); builder.faultMessage(currentOrNull(currentText));
} else if (qName.equals("spotPrice")) { } else if (qName.equals("spotPrice")) {
String price = currentOrNull(); String price = currentOrNull(currentText);
if (price != null) if (price != null)
builder.spotPrice(Float.parseFloat(price)); builder.spotPrice(Float.parseFloat(price));
} else if (qName.equals("type")) { } else if (qName.equals("type")) {
String type = currentOrNull(); String type = currentOrNull(currentText);
if (type != null) if (type != null)
builder.type(SpotInstanceRequest.Type.fromValue(type)); builder.type(SpotInstanceRequest.Type.fromValue(type));
} else if (qName.equals("state")) { } else if (qName.equals("state")) {
String state = currentOrNull(); String state = currentOrNull(currentText);
if (state != null) if (state != null)
builder.state(SpotInstanceRequest.State.fromValue(state)); builder.state(SpotInstanceRequest.State.fromValue(state));
} else if (qName.equals("createTime")) { } else if (qName.equals("createTime")) {
String createTime = currentOrNull(); String createTime = currentOrNull(currentText);
if (createTime != null) if (createTime != null)
builder.createTime(dateService.iso8601DateParse(createTime)); builder.createTime(dateService.iso8601DateParse(createTime));
} else if (qName.equals("productDescription")) { } else if (qName.equals("productDescription")) {
builder.productDescription(currentOrNull()); builder.productDescription(currentOrNull(currentText));
} }
currentText = new StringBuilder(); currentText = new StringBuilder();
} }

View File

@ -48,6 +48,7 @@ import org.jclouds.rest.RestContextFactory;
import org.jclouds.scriptbuilder.domain.Statements; import org.jclouds.scriptbuilder.domain.Statements;
import org.testng.annotations.Test; import org.testng.annotations.Test;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet; import com.google.common.collect.ImmutableSet;
import com.google.common.collect.ImmutableSortedSet; import com.google.common.collect.ImmutableSortedSet;
import com.google.common.collect.Iterables; import com.google.common.collect.Iterables;
@ -66,8 +67,15 @@ public class AWSEC2ComputeServiceLiveTest extends EC2ComputeServiceLiveTest {
group = "ec2"; group = "ec2";
} }
// aws-ec2 supports userMetadata
@Override @Override
@Test(enabled = false, dependsOnMethods = "testCompareSizes") protected void checkUserMetadataInNodeEquals(NodeMetadata node, ImmutableMap<String, String> userMetadata) {
assert node.getUserMetadata().equals(userMetadata) : String.format("node userMetadata did not match %s %s",
userMetadata, node);
}
@Override
@Test(dependsOnMethods = "testCompareSizes")
public void testExtendedOptionsAndLogin() throws Exception { public void testExtendedOptionsAndLogin() throws Exception {
AWSSecurityGroupClient securityGroupClient = AWSEC2Client.class.cast(context.getProviderSpecificContext().getApi()) AWSSecurityGroupClient securityGroupClient = AWSEC2Client.class.cast(context.getProviderSpecificContext().getApi())
.getSecurityGroupServices(); .getSecurityGroupServices();
@ -84,6 +92,9 @@ public class AWSEC2ComputeServiceLiveTest extends EC2ComputeServiceLiveTest {
Date before = new Date(); Date before = new Date();
ImmutableMap<String, String> userMetadata = ImmutableMap.<String, String> of("Name", group);
options.userMetadata(userMetadata);
options.as(AWSEC2TemplateOptions.class).enableMonitoring(); options.as(AWSEC2TemplateOptions.class).enableMonitoring();
options.as(AWSEC2TemplateOptions.class).spotPrice(0.3f); options.as(AWSEC2TemplateOptions.class).spotPrice(0.3f);
@ -113,6 +124,9 @@ public class AWSEC2ComputeServiceLiveTest extends EC2ComputeServiceLiveTest {
Set<? extends NodeMetadata> nodes = client.createNodesInGroup(group, 1, options); Set<? extends NodeMetadata> nodes = client.createNodesInGroup(group, 1, options);
NodeMetadata first = Iterables.get(nodes, 0); NodeMetadata first = Iterables.get(nodes, 0);
checkUserMetadataInNodeEquals(first, userMetadata);
assert first.getCredentials() != null : first; assert first.getCredentials() != null : first;
assert first.getCredentials().identity != null : first; assert first.getCredentials().identity != null : first;
@ -159,46 +173,4 @@ public class AWSEC2ComputeServiceLiveTest extends EC2ComputeServiceLiveTest {
} }
} }
@Test(enabled = false, dependsOnMethods = "testCompareSizes")
public void testSubnetId() throws Exception {
String subnetId = System.getProperty("test.subnetId");
if (subnetId == null) {
// Skip test and return
return;
}
InstanceClient instanceClient = EC2Client.class.cast(context.getProviderSpecificContext().getApi())
.getInstanceServices();
String group = this.group + "g";
TemplateOptions options = client.templateOptions();
options.as(AWSEC2TemplateOptions.class).subnetId(subnetId).spotPrice(0.3f);
String startedId = null;
String nodeId = null;
try {
Set<? extends NodeMetadata> nodes = client.createNodesInGroup(group, 1, options);
NodeMetadata first = Iterables.get(nodes, 0);
assert first.getCredentials() != null : first;
assert first.getCredentials().identity != null : first;
startedId = Iterables.getOnlyElement(nodes).getProviderId();
nodeId = Iterables.getOnlyElement(nodes).getId();
AWSRunningInstance instance = AWSRunningInstance.class.cast(getInstance(instanceClient, startedId));
assertEquals(instance.getSubnetId(), subnetId);
} finally {
if (nodeId != null)
client.destroyNode(nodeId);
}
}
} }

View File

@ -92,7 +92,7 @@ public class AWSRunningInstanceToNodeMetadataTest {
"/dev/sda1", "/dev/sda1",
new BlockDevice("vol-5829fc32", Attachment.Status.ATTACHED, dateService new BlockDevice("vol-5829fc32", Attachment.Status.ATTACHED, dateService
.iso8601DateParse("2011-08-16T13:41:19.000Z"), true)) .iso8601DateParse("2011-08-16T13:41:19.000Z"), true))
.virtualizationType("paravirtual").build(),// .virtualizationType("paravirtual").tag("Name", "foo").build(),//
new AWSRunningInstance.Builder().region(defaultRegion).instanceId("i-931444f2").imageId("ami-63be790a") new AWSRunningInstance.Builder().region(defaultRegion).instanceId("i-931444f2").imageId("ami-63be790a")
.instanceState(InstanceState.RUNNING).privateDnsName("ip-10-212-185-8.ec2.internal").dnsName( .instanceState(InstanceState.RUNNING).privateDnsName("ip-10-212-185-8.ec2.internal").dnsName(
"ec2-50-19-207-248.compute-1.amazonaws.com").keyName( "ec2-50-19-207-248.compute-1.amazonaws.com").keyName(
@ -107,10 +107,12 @@ public class AWSRunningInstanceToNodeMetadataTest {
.iso8601DateParse("2011-08-16T13:41:19.000Z"), true)).virtualizationType( .iso8601DateParse("2011-08-16T13:41:19.000Z"), true)).virtualizationType(
"paravirtual").build()); "paravirtual").build());
assertEquals(parser.apply(Iterables.get(contents, 0)), new NodeMetadataBuilder().state(NodeState.RUNNING).group( assertEquals(
"zkclustertest").hostname("ip-10-212-81-7").privateAddresses(ImmutableSet.of("10.212.81.7")) parser.apply(Iterables.get(contents, 0)).toString(),
.publicAddresses(ImmutableSet.of("174.129.173.155")).imageId("us-east-1/ami-63be790a").id( new NodeMetadataBuilder().state(NodeState.RUNNING).group("zkclustertest").hostname("ip-10-212-81-7")
"us-east-1/i-911444f0").providerId("i-911444f0").build()); .privateAddresses(ImmutableSet.of("10.212.81.7")).publicAddresses(ImmutableSet.of("174.129.173.155"))
.imageId("us-east-1/ami-63be790a").id("us-east-1/i-911444f0").providerId("i-911444f0")
.userMetadata(ImmutableMap.of("Name", "foo")).build().toString());
assertEquals(parser.apply(Iterables.get(contents, 1)), new NodeMetadataBuilder().state(NodeState.RUNNING).group( assertEquals(parser.apply(Iterables.get(contents, 1)), new NodeMetadataBuilder().state(NodeState.RUNNING).group(
"zkclustertest").hostname("ip-10-212-185-8").privateAddresses(ImmutableSet.of("10.212.185.8")) "zkclustertest").hostname("ip-10-212-185-8").privateAddresses(ImmutableSet.of("10.212.185.8"))
.publicAddresses(ImmutableSet.of("50.19.207.248")).imageId("us-east-1/ami-63be790a").id( .publicAddresses(ImmutableSet.of("50.19.207.248")).imageId("us-east-1/ami-63be790a").id(

View File

@ -24,7 +24,6 @@ import org.jclouds.aws.ec2.domain.AWSRunningInstance;
import org.jclouds.aws.ec2.domain.LaunchSpecification; import org.jclouds.aws.ec2.domain.LaunchSpecification;
import org.jclouds.aws.ec2.domain.MonitoringState; import org.jclouds.aws.ec2.domain.MonitoringState;
import org.jclouds.aws.ec2.domain.SpotInstanceRequest; import org.jclouds.aws.ec2.domain.SpotInstanceRequest;
import org.jclouds.aws.ec2.functions.SpotInstanceRequestToAWSRunningInstance;
import org.jclouds.date.internal.SimpleDateFormatDateService; import org.jclouds.date.internal.SimpleDateFormatDateService;
import org.jclouds.ec2.domain.InstanceState; import org.jclouds.ec2.domain.InstanceState;
import org.testng.annotations.Test; import org.testng.annotations.Test;
@ -34,40 +33,51 @@ import org.testng.annotations.Test;
* *
* @author Adrian Cole * @author Adrian Cole
*/ */
// NOTE:without testName, this will not call @Before* and fail w/NPE during surefire // NOTE:without testName, this will not call @Before* and fail w/NPE during
// surefire
@Test(groups = "unit", testName = "SpotInstanceRequestToAWSRunningInstanceTest") @Test(groups = "unit", testName = "SpotInstanceRequestToAWSRunningInstanceTest")
public class SpotInstanceRequestToAWSRunningInstanceTest { public class SpotInstanceRequestToAWSRunningInstanceTest {
public void testConvert() { public void testConvert() {
SpotInstanceRequest input = SpotInstanceRequest.builder().region("us-east-1").id("sir-228e6406") SpotInstanceRequest input = SpotInstanceRequest
.spotPrice(0.001f).type(SpotInstanceRequest.Type.ONE_TIME).state(SpotInstanceRequest.State.OPEN) .builder()
.region("us-east-1")
.id("sir-228e6406")
.spotPrice(0.001f)
.type(SpotInstanceRequest.Type.ONE_TIME)
.state(SpotInstanceRequest.State.OPEN)
.launchSpecification( .launchSpecification(
LaunchSpecification.builder().imageId("ami-595a0a1c").securityGroupName("default").instanceType( LaunchSpecification.builder().imageId("ami-595a0a1c").securityGroupName("default")
"m1.large").mapNewVolumeToDevice("/dev/sda1", 1, true).mapEBSSnapshotToDevice( .instanceType("m1.large").mapNewVolumeToDevice("/dev/sda1", 1, true)
"/dev/sda2", "snap-1ea27576", 1, true).mapEphemeralDeviceToDevice("/dev/sda3", "vre1") .mapEBSSnapshotToDevice("/dev/sda2", "snap-1ea27576", 1, true)
.monitoringEnabled(false).build()).createTime( .mapEphemeralDeviceToDevice("/dev/sda3", "vre1").monitoringEnabled(false).build())
new SimpleDateFormatDateService().iso8601DateParse("2011-03-08T03:30:36.000Z")) .createTime(new SimpleDateFormatDateService().iso8601DateParse("2011-03-08T03:30:36.000Z"))
.productDescription("Linux/UNIX").build(); .productDescription("Linux/UNIX").tag("foo", "bar").build();
assertEquals(new SpotInstanceRequestToAWSRunningInstance().apply(input), AWSRunningInstance.builder().region( assertEquals(
"us-east-1").instanceId("sir-228e6406").spotInstanceRequestId("sir-228e6406").instanceState( new SpotInstanceRequestToAWSRunningInstance().apply(input),
InstanceState.PENDING).imageId("ami-595a0a1c").groupId("default").instanceType("m1.large") AWSRunningInstance.builder().region("us-east-1").instanceId("sir-228e6406")
.spotInstanceRequestId("sir-228e6406").instanceState(InstanceState.PENDING).imageId("ami-595a0a1c")
.groupId("default").instanceType("m1.large").tag("foo", "bar")
.monitoringState(MonitoringState.PENDING).build()); .monitoringState(MonitoringState.PENDING).build());
} }
public void testConvertWhenNotOpenReturnsNull() { public void testConvertWhenNotOpenReturnsNull() {
assertEquals(new SpotInstanceRequestToAWSRunningInstance().apply(SpotInstanceRequest.builder() assertEquals(
.region("us-east-1").id("sir-228e6406").type(SpotInstanceRequest.Type.ONE_TIME).state( new SpotInstanceRequestToAWSRunningInstance().apply(SpotInstanceRequest.builder().region("us-east-1")
SpotInstanceRequest.State.ACTIVE).build()), null); .id("sir-228e6406").type(SpotInstanceRequest.Type.ONE_TIME).state(SpotInstanceRequest.State.ACTIVE)
.build()), null);
assertEquals(new SpotInstanceRequestToAWSRunningInstance().apply(SpotInstanceRequest.builder() assertEquals(
.region("us-east-1").id("sir-228e6406").type(SpotInstanceRequest.Type.ONE_TIME).state( new SpotInstanceRequestToAWSRunningInstance().apply(SpotInstanceRequest.builder().region("us-east-1")
SpotInstanceRequest.State.CANCELLED).build()), null); .id("sir-228e6406").type(SpotInstanceRequest.Type.ONE_TIME)
.state(SpotInstanceRequest.State.CANCELLED).build()), null);
assertEquals(new SpotInstanceRequestToAWSRunningInstance().apply(SpotInstanceRequest.builder() assertEquals(
.region("us-east-1").id("sir-228e6406").type(SpotInstanceRequest.Type.ONE_TIME).state( new SpotInstanceRequestToAWSRunningInstance().apply(SpotInstanceRequest.builder().region("us-east-1")
SpotInstanceRequest.State.UNRECOGNIZED).build()), null); .id("sir-228e6406").type(SpotInstanceRequest.Type.ONE_TIME)
.state(SpotInstanceRequest.State.UNRECOGNIZED).build()), null);
} }
} }

View File

@ -18,9 +18,10 @@
*/ */
package org.jclouds.aws.ec2.services; package org.jclouds.aws.ec2.services;
import static com.google.common.base.Preconditions.*; import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.collect.Iterables.*; import static com.google.common.collect.Iterables.getOnlyElement;
import static org.testng.Assert.*; import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertNotNull;
import java.util.Properties; import java.util.Properties;
import java.util.Set; import java.util.Set;
@ -53,7 +54,7 @@ import com.google.inject.Module;
* *
* @author grkvlt@apache.org * @author grkvlt@apache.org
*/ */
@Test(groups = "live", sequential = true) @Test(groups = "live", singleThreaded = true)
public class TagClientLiveTest { public class TagClientLiveTest {
private TagClient client; private TagClient client;

View File

@ -90,39 +90,56 @@ public class AWSDescribeInstancesResponseHandlerTest extends BaseEC2HandlerTest
Set<Reservation<AWSRunningInstance>> contents = ImmutableSet.of(new Reservation<AWSRunningInstance>( Set<Reservation<AWSRunningInstance>> contents = ImmutableSet.of(new Reservation<AWSRunningInstance>(
defaultRegion, ImmutableSet.of("jclouds#ec2-s#us-east-1"), ImmutableSet.of( defaultRegion, ImmutableSet.of("jclouds#ec2-s#us-east-1"), ImmutableSet.of(
new AWSRunningInstance.Builder().region(defaultRegion).instanceId("i-911444f0").imageId( new AWSRunningInstance.Builder()
"ami-63be790a").instanceState(InstanceState.RUNNING).privateDnsName( .region(defaultRegion)
"ip-10-212-81-7.ec2.internal").dnsName("ec2-174-129-173-155.compute-1.amazonaws.com") .instanceId("i-911444f0")
.keyName("jclouds#zkclustertest#us-east-1#23").amiLaunchIndex("0").instanceType( .imageId("ami-63be790a")
"t1.micro").launchTime( .instanceState(InstanceState.RUNNING)
dateService.iso8601DateParse("2011-08-16T13:40:50.000Z")).availabilityZone( .privateDnsName("ip-10-212-81-7.ec2.internal")
"us-east-1c").kernelId("aki-427d952b").monitoringState( .dnsName("ec2-174-129-173-155.compute-1.amazonaws.com")
MonitoringState.DISABLED).privateIpAddress("10.212.81.7").ipAddress( .keyName("jclouds#zkclustertest#us-east-1#23")
"174.129.173.155").securityGroupIdToNames( .amiLaunchIndex("0")
ImmutableMap.<String, String> of("sg-ef052b86", .instanceType("t1.micro")
"jclouds#zkclustertest#us-east-1")).rootDeviceType( .launchTime(dateService.iso8601DateParse("2011-08-16T13:40:50.000Z"))
RootDeviceType.EBS).rootDeviceName("/dev/sda1").device( .availabilityZone("us-east-1c")
.kernelId("aki-427d952b")
.monitoringState(MonitoringState.DISABLED)
.privateIpAddress("10.212.81.7")
.ipAddress("174.129.173.155")
.securityGroupIdToName("sg-ef052b86", "jclouds#zkclustertest#us-east-1")
.tag("Name", "ec2-o")
.rootDeviceType(RootDeviceType.EBS)
.rootDeviceName("/dev/sda1")
.device(
"/dev/sda1", "/dev/sda1",
new BlockDevice("vol-5829fc32", Attachment.Status.ATTACHED, dateService new BlockDevice("vol-5829fc32", Attachment.Status.ATTACHED, dateService
.iso8601DateParse("2011-08-16T13:41:19.000Z"), true)) .iso8601DateParse("2011-08-16T13:41:19.000Z"), true))
.virtualizationType("paravirtual").build(),// .virtualizationType("paravirtual").build(),//
new AWSRunningInstance.Builder().region(defaultRegion).instanceId("i-931444f2").imageId( new AWSRunningInstance.Builder()
"ami-63be790a").instanceState(InstanceState.RUNNING).privateDnsName( .region(defaultRegion)
"ip-10-212-185-8.ec2.internal").dnsName("ec2-50-19-207-248.compute-1.amazonaws.com") .instanceId("i-931444f2")
.keyName("jclouds#zkclustertest#us-east-1#23").amiLaunchIndex("0").instanceType( .imageId("ami-63be790a")
"t1.micro").launchTime( .instanceState(InstanceState.RUNNING)
dateService.iso8601DateParse("2011-08-16T13:40:50.000Z")).availabilityZone( .privateDnsName("ip-10-212-185-8.ec2.internal")
"us-east-1c").kernelId("aki-427d952b").monitoringState( .dnsName("ec2-50-19-207-248.compute-1.amazonaws.com")
MonitoringState.DISABLED).privateIpAddress("10.212.185.8").ipAddress( .keyName("jclouds#zkclustertest#us-east-1#23")
"50.19.207.248").securityGroupIdToNames( .amiLaunchIndex("0")
ImmutableMap.<String, String> of("sg-ef052b86", .instanceType("t1.micro")
"jclouds#zkclustertest#us-east-1")).rootDeviceType( .launchTime(dateService.iso8601DateParse("2011-08-16T13:40:50.000Z"))
RootDeviceType.EBS).rootDeviceName("/dev/sda1").device( .availabilityZone("us-east-1c")
.kernelId("aki-427d952b")
.monitoringState(MonitoringState.DISABLED)
.privateIpAddress("10.212.185.8")
.ipAddress("50.19.207.248")
.securityGroupIdToNames(
ImmutableMap.<String, String> of("sg-ef052b86", "jclouds#zkclustertest#us-east-1"))
.rootDeviceType(RootDeviceType.EBS)
.rootDeviceName("/dev/sda1")
.device(
"/dev/sda1", "/dev/sda1",
new BlockDevice("vol-5029fc3a", Attachment.Status.ATTACHED, dateService new BlockDevice("vol-5029fc3a", Attachment.Status.ATTACHED, dateService
.iso8601DateParse("2011-08-16T13:41:19.000Z"), true)) .iso8601DateParse("2011-08-16T13:41:19.000Z"), true))
.virtualizationType("paravirtual").build()), defaultRegion, defaultRegion, .virtualizationType("paravirtual").build()), defaultRegion, defaultRegion, defaultRegion));
defaultRegion));
Set<Reservation<? extends RunningInstance>> result = parseAWSRunningInstances("/describe_instances_latest.xml"); Set<Reservation<? extends RunningInstance>> result = parseAWSRunningInstances("/describe_instances_latest.xml");

View File

@ -108,10 +108,11 @@ public class SpotInstanceHandlerTest extends BaseEC2HandlerTest {
.launchedAvailabilityZone("us-east-1b") .launchedAvailabilityZone("us-east-1b")
.launchSpecification( .launchSpecification(
LaunchSpecification.builder().imageId("ami-8e1fece7") LaunchSpecification.builder().imageId("ami-8e1fece7")
.securityGroupIdToName("sg-83e1c4eb", "jclouds#adriancole-ec2unssh#us-east-1").instanceType("t1.micro") .securityGroupIdToName("sg-83e1c4eb", "jclouds#adriancole-ec2unssh#us-east-1")
.monitoringEnabled(false).keyName("jclouds#adriancole-ec2unssh").build()) .instanceType("t1.micro").monitoringEnabled(false).keyName("jclouds#adriancole-ec2unssh")
.build())
.createTime(new SimpleDateFormatDateService().iso8601DateParse("2011-07-29T05:27:39.000Z")) .createTime(new SimpleDateFormatDateService().iso8601DateParse("2011-07-29T05:27:39.000Z"))
.productDescription("Linux/UNIX").build(); .productDescription("Linux/UNIX").tag("Name", "ec2-o").build();
SpotInstanceHandler handler = injector.getInstance(SpotInstanceHandler.class); SpotInstanceHandler handler = injector.getInstance(SpotInstanceHandler.class);
addDefaultRegionToHandler(handler); addDefaultRegionToHandler(handler);
SpotInstanceRequest result = factory.create(handler).parse(is); SpotInstanceRequest result = factory.create(handler).parse(is);

View File

@ -61,6 +61,12 @@
<virtualizationType>paravirtual</virtualizationType> <virtualizationType>paravirtual</virtualizationType>
<clientToken/> <clientToken/>
<hypervisor>xen</hypervisor> <hypervisor>xen</hypervisor>
<tagSet>
<item>
<key>Name</key>
<value>ec2-o</value>
</item>
</tagSet>
</item> </item>
<item> <item>
<instanceId>i-931444f2</instanceId> <instanceId>i-931444f2</instanceId>

View File

@ -25,6 +25,12 @@
<instanceId>i-ef308e8e</instanceId> <instanceId>i-ef308e8e</instanceId>
<createTime>2011-07-29T05:27:39.000Z</createTime> <createTime>2011-07-29T05:27:39.000Z</createTime>
<productDescription>Linux/UNIX</productDescription> <productDescription>Linux/UNIX</productDescription>
<tagSet>
<item>
<key>Name</key>
<value>ec2-o</value>
</item>
</tagSet>
<launchedAvailabilityZone>us-east-1b</launchedAvailabilityZone> <launchedAvailabilityZone>us-east-1b</launchedAvailabilityZone>
</item> </item>
</spotInstanceRequestSet> </spotInstanceRequestSet>

View File

@ -25,7 +25,7 @@ import org.testng.annotations.Test;
* *
* @author Adrian Cole * @author Adrian Cole
*/ */
@Test(groups = "live", sequential = true, testName = "CloudServersUSComputeServiceLiveTest") @Test(groups = "live", singleThreaded = true, testName = "CloudServersUSComputeServiceLiveTest")
public class CloudServersUSComputeServiceLiveTest extends CloudServersComputeServiceLiveTest { public class CloudServersUSComputeServiceLiveTest extends CloudServersComputeServiceLiveTest {
public CloudServersUSComputeServiceLiveTest() { public CloudServersUSComputeServiceLiveTest() {

View File

@ -18,20 +18,24 @@
*/ */
package org.jclouds.gogrid.compute.options; package org.jclouds.gogrid.compute.options;
import java.util.Map;
import org.jclouds.compute.ComputeService; import org.jclouds.compute.ComputeService;
import org.jclouds.compute.options.TemplateOptions; import org.jclouds.compute.options.TemplateOptions;
import org.jclouds.io.Payload; import org.jclouds.io.Payload;
/** /**
* Contains options supported by the {@link ComputeService#createNodesInGroup(String, int, TemplateOptions)} * Contains options supported by the
* and {@link ComputeService#runNodesWithTag(String, int, TemplateOptions)} operations on * {@link ComputeService#createNodesInGroup(String, int, TemplateOptions)} and
* the <em>gogrid</em> provider. * {@link ComputeService#runNodesWithTag(String, int, TemplateOptions)}
* operations on the <em>gogrid</em> provider.
* *
* <h2>Usage</h2> * <h2>Usage</h2> The recommended way to instantiate a
* The recommended way to instantiate a {@link GoGridTemplateOptions} object is to statically * {@link GoGridTemplateOptions} object is to statically import
* import {@code GoGridTemplateOptions.*} and invoke a static creation method followed by an * {@code GoGridTemplateOptions.*} and invoke a static creation method followed
* instance mutator (if needed): * by an instance mutator (if needed):
* <p> * <p>
*
* <pre> * <pre>
* import static org.jclouds.compute.options.GoGridTemplateOptions.Builder.*; * import static org.jclouds.compute.options.GoGridTemplateOptions.Builder.*;
* ComputeService client = // get connection * ComputeService client = // get connection
@ -109,11 +113,19 @@ public class GoGridTemplateOptions extends TemplateOptions implements Cloneable
} }
/** /**
* @see TemplateOptions#withMetadata() * @see TemplateOptions#userMetadata(Map)
*/ */
public static GoGridTemplateOptions withMetadata() { public static GoGridTemplateOptions userMetadata(Map<String, String> userMetadata) {
GoGridTemplateOptions options = new GoGridTemplateOptions(); GoGridTemplateOptions options = new GoGridTemplateOptions();
return GoGridTemplateOptions.class.cast(options.withMetadata()); return GoGridTemplateOptions.class.cast(options.userMetadata(userMetadata));
}
/**
* @see TemplateOptions#userMetadata(String, String)
*/
public static GoGridTemplateOptions userMetadata(String key, String value) {
GoGridTemplateOptions options = new GoGridTemplateOptions();
return GoGridTemplateOptions.class.cast(options.userMetadata(key, value));
} }
} }
@ -187,10 +199,18 @@ public class GoGridTemplateOptions extends TemplateOptions implements Cloneable
} }
/** /**
* @see TemplateOptions#withMetadata() * {@inheritDoc}
*/ */
@Override @Override
public GoGridTemplateOptions withMetadata() { public GoGridTemplateOptions userMetadata(Map<String, String> userMetadata) {
return GoGridTemplateOptions.class.cast(super.withMetadata()); return GoGridTemplateOptions.class.cast(super.userMetadata(userMetadata));
}
/**
* {@inheritDoc}
*/
@Override
public GoGridTemplateOptions userMetadata(String key, String value) {
return GoGridTemplateOptions.class.cast(super.userMetadata(key, value));
} }
} }

View File

@ -37,6 +37,7 @@ import org.jclouds.rest.RestContext;
import org.jclouds.sshj.config.SshjSshClientModule; import org.jclouds.sshj.config.SshjSshClientModule;
import org.testng.annotations.Test; import org.testng.annotations.Test;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Iterables; import com.google.common.collect.Iterables;
import com.google.inject.Module; import com.google.inject.Module;
@ -56,6 +57,13 @@ public class GoGridComputeServiceLiveTest extends BaseComputeServiceLiveTest {
return new SshjSshClientModule(); return new SshjSshClientModule();
} }
// gogrid does not support metadata
@Override
protected void checkUserMetadataInNodeEquals(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);
}
protected void checkResponseEqualsHostname(ExecResponse execResponse, NodeMetadata node1) { protected void checkResponseEqualsHostname(ExecResponse execResponse, NodeMetadata node1) {
// hostname is not predictable based on node metadata // hostname is not predictable based on node metadata
} }

View File

@ -19,10 +19,13 @@
package org.jclouds.rimuhosting.miro.compute; package org.jclouds.rimuhosting.miro.compute;
import org.jclouds.compute.BaseComputeServiceLiveTest; import org.jclouds.compute.BaseComputeServiceLiveTest;
import org.jclouds.compute.domain.NodeMetadata;
import org.jclouds.ssh.jsch.config.JschSshClientModule; import org.jclouds.ssh.jsch.config.JschSshClientModule;
import org.testng.annotations.BeforeClass; import org.testng.annotations.BeforeClass;
import org.testng.annotations.Test; import org.testng.annotations.Test;
import com.google.common.collect.ImmutableMap;
/** /**
* @author Ivan Meredith * @author Ivan Meredith
*/ */
@ -38,6 +41,13 @@ public class RimuHostingComputeServiceLiveTest extends BaseComputeServiceLiveTes
group = "rimuhosting.jclouds"; group = "rimuhosting.jclouds";
} }
// rimuhosting does not support metadata
@Override
protected void checkUserMetadataInNodeEquals(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);
}
@Override @Override
protected JschSshClientModule getSshModule() { protected JschSshClientModule getSshModule() {
return new JschSshClientModule(); return new JschSshClientModule();

View File

@ -22,21 +22,25 @@ import java.util.Properties;
import org.jclouds.Constants; import org.jclouds.Constants;
import org.jclouds.compute.BaseComputeServiceLiveTest; import org.jclouds.compute.BaseComputeServiceLiveTest;
import org.jclouds.compute.domain.NodeMetadata;
import org.jclouds.sshj.config.SshjSshClientModule; import org.jclouds.sshj.config.SshjSshClientModule;
import org.testng.annotations.Test; import org.testng.annotations.Test;
import com.google.common.collect.ImmutableMap;
import com.google.inject.Module; import com.google.inject.Module;
/** /**
* Takes a long time to list nodes. Average response time is about 10-15 seconds per vm. * Takes a long time to list nodes. Average response time is about 10-15 seconds
* Hence this test does not complete and is disabled until performance improves. * per vm. Hence this test does not complete and is disabled until performance
* improves.
*
* @author Kedar Dave * @author Kedar Dave
* *
*/ */
@Test(enabled = true, groups = "live") @Test(enabled = true, groups = "live")
public class VPDCComputeServiceLiveTestDisabled extends BaseComputeServiceLiveTest { public class VPDCComputeServiceLiveTestDisabled extends BaseComputeServiceLiveTest {
public VPDCComputeServiceLiveTestDisabled(){ public VPDCComputeServiceLiveTestDisabled() {
provider = "savvis-symphonyvpdc"; provider = "savvis-symphonyvpdc";
} }
@ -45,6 +49,14 @@ public class VPDCComputeServiceLiveTestDisabled extends BaseComputeServiceLiveTe
group = "savvis-symphonyvpdc"; group = "savvis-symphonyvpdc";
} }
// savvis does not support metadata
@Override
protected void checkUserMetadataInNodeEquals(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);
}
@Override @Override
protected Properties setupProperties() { protected Properties setupProperties() {
Properties overrides = super.setupProperties(); Properties overrides = super.setupProperties();

View File

@ -19,9 +19,12 @@
package org.jclouds.slicehost.compute; package org.jclouds.slicehost.compute;
import org.jclouds.compute.BaseComputeServiceLiveTest; import org.jclouds.compute.BaseComputeServiceLiveTest;
import org.jclouds.compute.domain.NodeMetadata;
import org.jclouds.sshj.config.SshjSshClientModule; import org.jclouds.sshj.config.SshjSshClientModule;
import org.testng.annotations.Test; import org.testng.annotations.Test;
import com.google.common.collect.ImmutableMap;
/** /**
* *
* Generally disabled, as it incurs higher fees. * Generally disabled, as it incurs higher fees.
@ -39,6 +42,12 @@ public class SlicehostComputeServiceLiveTest extends BaseComputeServiceLiveTest
return new SshjSshClientModule(); return new SshjSshClientModule();
} }
// slicehost does not support metadata
@Override
protected void checkUserMetadataInNodeEquals(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);
}
@Test(expectedExceptions = UnsupportedOperationException.class) @Test(expectedExceptions = UnsupportedOperationException.class)
public void testSuspendResume() throws Exception { public void testSuspendResume() throws Exception {
super.testSuspendResume(); super.testSuspendResume();

View File

@ -21,6 +21,8 @@ package org.jclouds.softlayer.compute.options;
import static com.google.common.base.Preconditions.checkArgument; import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull; import static com.google.common.base.Preconditions.checkNotNull;
import java.util.Map;
import org.jclouds.compute.ComputeService; import org.jclouds.compute.ComputeService;
import org.jclouds.compute.options.TemplateOptions; import org.jclouds.compute.options.TemplateOptions;
import org.jclouds.io.Payload; import org.jclouds.io.Payload;
@ -31,12 +33,13 @@ import com.google.common.net.InternetDomainName;
/** /**
* Contains options supported by the * Contains options supported by the
* {@link ComputeService#createNodesInGroup(String, int, TemplateOptions)} and * {@link ComputeService#createNodesInGroup(String, int, TemplateOptions)} and
* {@link ComputeService#runNodesWithTag(String, int, TemplateOptions)} operations on the * {@link ComputeService#runNodesWithTag(String, int, TemplateOptions)}
* <em>gogrid</em> provider. * operations on the <em>gogrid</em> provider.
* *
* <h2>Usage</h2> The recommended way to instantiate a {@link SoftLayerTemplateOptions} object is to * <h2>Usage</h2> The recommended way to instantiate a
* statically import {@code SoftLayerTemplateOptions.*} and invoke a static creation method followed * {@link SoftLayerTemplateOptions} object is to statically import
* by an instance mutator (if needed): * {@code SoftLayerTemplateOptions.*} and invoke a static creation method
* followed by an instance mutator (if needed):
* <p> * <p>
* *
* <pre> * <pre>
@ -69,8 +72,8 @@ public class SoftLayerTemplateOptions extends TemplateOptions implements Cloneab
} }
/** /**
* will replace the default domain used when ordering virtual guests. Note this needs to contain * will replace the default domain used when ordering virtual guests. Note
* a public suffix! * this needs to contain a public suffix!
* *
* @see VirtualGuestClient#orderVirtualGuest * @see VirtualGuestClient#orderVirtualGuest
* @see InternetDomainName#hasPublicSuffix * @see InternetDomainName#hasPublicSuffix
@ -144,11 +147,19 @@ public class SoftLayerTemplateOptions extends TemplateOptions implements Cloneab
} }
/** /**
* @see TemplateOptions#withMetadata() * @see TemplateOptions#userMetadata(Map)
*/ */
public static SoftLayerTemplateOptions withMetadata() { public static SoftLayerTemplateOptions userMetadata(Map<String, String> userMetadata) {
SoftLayerTemplateOptions options = new SoftLayerTemplateOptions(); SoftLayerTemplateOptions options = new SoftLayerTemplateOptions();
return SoftLayerTemplateOptions.class.cast(options.withMetadata()); return SoftLayerTemplateOptions.class.cast(options.userMetadata(userMetadata));
}
/**
* @see TemplateOptions#userMetadata(String, String)
*/
public static SoftLayerTemplateOptions userMetadata(String key, String value) {
SoftLayerTemplateOptions options = new SoftLayerTemplateOptions();
return SoftLayerTemplateOptions.class.cast(options.userMetadata(key, value));
} }
} }
@ -222,10 +233,18 @@ public class SoftLayerTemplateOptions extends TemplateOptions implements Cloneab
} }
/** /**
* @see TemplateOptions#withMetadata() * {@inheritDoc}
*/ */
@Override @Override
public SoftLayerTemplateOptions withMetadata() { public SoftLayerTemplateOptions userMetadata(Map<String, String> userMetadata) {
return SoftLayerTemplateOptions.class.cast(super.withMetadata()); return SoftLayerTemplateOptions.class.cast(super.userMetadata(userMetadata));
}
/**
* {@inheritDoc}
*/
@Override
public SoftLayerTemplateOptions userMetadata(String key, String value) {
return SoftLayerTemplateOptions.class.cast(super.userMetadata(key, value));
} }
} }

View File

@ -38,6 +38,7 @@ import org.jclouds.trmk.vcloud_0_8.domain.VApp;
import org.jclouds.trmk.vcloud_0_8.reference.VCloudConstants; import org.jclouds.trmk.vcloud_0_8.reference.VCloudConstants;
import org.testng.annotations.Test; import org.testng.annotations.Test;
import com.google.common.collect.ImmutableMap;
import com.google.inject.Module; import com.google.inject.Module;
/** /**
@ -66,6 +67,13 @@ public class TerremarkECloudComputeServiceLiveTest extends BaseComputeServiceLiv
group = "te"; group = "te";
} }
// terremark does not support metadata
@Override
protected void checkUserMetadataInNodeEquals(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);
}
@Override @Override
protected Template buildTemplate(TemplateBuilder templateBuilder) { protected Template buildTemplate(TemplateBuilder templateBuilder) {
Template template = super.buildTemplate(templateBuilder); Template template = super.buildTemplate(templateBuilder);

View File

@ -35,12 +35,14 @@ import org.jclouds.trmk.vcloud_0_8.TerremarkVCloudClient;
import org.jclouds.trmk.vcloud_0_8.domain.VApp; import org.jclouds.trmk.vcloud_0_8.domain.VApp;
import org.testng.annotations.Test; import org.testng.annotations.Test;
import com.google.common.collect.ImmutableMap;
/** /**
* *
* *
* @author Adrian Cole * @author Adrian Cole
*/ */
@Test(groups = "live", enabled = true, sequential = true) @Test(groups = "live", enabled = true, singleThreaded = true)
public class TerremarkVCloudExpressComputeServiceLiveTest extends BaseComputeServiceLiveTest { public class TerremarkVCloudExpressComputeServiceLiveTest extends BaseComputeServiceLiveTest {
public TerremarkVCloudExpressComputeServiceLiveTest() { public TerremarkVCloudExpressComputeServiceLiveTest() {
provider = "trmk-vcloudexpress"; provider = "trmk-vcloudexpress";
@ -60,6 +62,13 @@ public class TerremarkVCloudExpressComputeServiceLiveTest extends BaseComputeSer
return template; return template;
} }
// terremark does not support metadata
@Override
protected void checkUserMetadataInNodeEquals(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);
}
@Override @Override
public void testListImages() throws Exception { public void testListImages() throws Exception {
for (Image image : client.listImages()) { for (Image image : client.listImages()) {

View File

@ -25,6 +25,7 @@ import java.util.Properties;
import org.jclouds.compute.BaseComputeServiceLiveTest; import org.jclouds.compute.BaseComputeServiceLiveTest;
import org.jclouds.compute.ComputeServiceContextFactory; import org.jclouds.compute.ComputeServiceContextFactory;
import org.jclouds.compute.domain.NodeMetadata;
import org.jclouds.compute.domain.OsFamily; import org.jclouds.compute.domain.OsFamily;
import org.jclouds.compute.domain.Template; import org.jclouds.compute.domain.Template;
import org.jclouds.rest.RestContext; import org.jclouds.rest.RestContext;
@ -32,10 +33,12 @@ import org.jclouds.servermanager.ServerManager;
import org.jclouds.ssh.jsch.config.JschSshClientModule; import org.jclouds.ssh.jsch.config.JschSshClientModule;
import org.testng.annotations.Test; import org.testng.annotations.Test;
import com.google.common.collect.ImmutableMap;
/** /**
* @author Adrian Cole * @author Adrian Cole
*/ */
@Test(groups = "live", enabled = true, sequential = true) @Test(groups = "live", enabled = true, singleThreaded = true)
public class ServerManagerComputeServiceLiveTest extends BaseComputeServiceLiveTest { public class ServerManagerComputeServiceLiveTest extends BaseComputeServiceLiveTest {
public ServerManagerComputeServiceLiveTest() { public ServerManagerComputeServiceLiveTest() {
provider = "servermanager"; provider = "servermanager";
@ -66,6 +69,13 @@ public class ServerManagerComputeServiceLiveTest extends BaseComputeServiceLiveT
return new JschSshClientModule(); return new JschSshClientModule();
} }
// servermanager does not support metadata
@Override
protected void checkUserMetadataInNodeEquals(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);
}
public void testAssignability() throws Exception { public void testAssignability() throws Exception {
@SuppressWarnings("unused") @SuppressWarnings("unused")
RestContext<ServerManager, ServerManager> goGridContext = new ComputeServiceContextFactory().createContext( RestContext<ServerManager, ServerManager> goGridContext = new ComputeServiceContextFactory().createContext(