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

View File

@ -21,6 +21,7 @@ package org.jclouds.byon.domain;
import java.io.InputStream;
import java.net.URI;
import java.util.List;
import java.util.Map;
import org.jclouds.byon.Node;
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.Builder;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.io.Closeables;
/**
@ -54,6 +56,8 @@ import com.google.common.io.Closeables;
* group: hadoop
* tags:
* - vanilla
* metadata:
* key1: val1
* username: kelvin
* credential: password_or_rsa
* or
@ -78,6 +82,7 @@ public class YamlNode {
public boolean os_64bit;
public String group;
public List<String> tags = Lists.newArrayList();
public Map<String, String> metadata = Maps.newLinkedHashMap();
public String username;
public String credential;
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)
.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)
.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.sudo_password).build();
}
@ -152,6 +157,8 @@ public class YamlNode {
prettier.put("group", in.group);
if (in.tags.size() != 0)
prettier.put("tags", in.tags);
if (in.metadata.size() != 0)
prettier.put("metadata", in.metadata);
if (in.username != null)
prettier.put("username", in.username);
if (in.credential != null)
@ -193,6 +200,7 @@ public class YamlNode {
yaml.login_port = arg0.getLoginPort();
yaml.group = arg0.getGroup();
yaml.tags = ImmutableList.copyOf(arg0.getTags());
yaml.metadata = ImmutableMap.copyOf(arg0.getMetadata());
yaml.username = arg0.getUsername();
yaml.credential = arg0.getCredential();
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.group(from.getGroup());
builder.tags(from.getTags());
builder.userMetadata(from.getMetadata());
builder.operatingSystem(OperatingSystem.builder().arch(from.getOsArch()).family(
OsFamily.fromValue(from.getOsFamily())).description(from.getOsDescription())
.version(from.getOsVersion()).build());

View File

@ -85,6 +85,7 @@ public class NodeToNodeMetadataTest {
.loginPort(loginPort)
.hostname("cluster-" + id + ".mydomain.com")
.location(location)
.userMetadata(ImmutableMap.of("Name", "foo"))
.state(NodeState.RUNNING)
.operatingSystem(
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
*/
public class NodesFromYamlTest {
public static final String key = new StringBuilder().append("-----BEGIN RSA PRIVATE KEY-----\n").append(
"MIIEowIBAAKCAQEAuzaE6azgUxwESX1rCGdJ5xpdrc1XC311bOGZBCE8NA+CpFh2\n").append(
"u01Vfv68NC4u6LFgdXSY1vQt6hiA5TNqQk0TyVfFAunbXgTekF6XqDPQUf1nq9aZ\n").append(
"lMvo4vlaLDKBkhG5HJE/pIa0iB+RMZLS0GhxsIWerEDmYdHKM25o\n").append("-----END RSA PRIVATE KEY-----\n")
public static final String key = new StringBuilder().append("-----BEGIN RSA PRIVATE KEY-----\n")
.append("MIIEowIBAAKCAQEAuzaE6azgUxwESX1rCGdJ5xpdrc1XC311bOGZBCE8NA+CpFh2\n")
.append("u01Vfv68NC4u6LFgdXSY1vQt6hiA5TNqQk0TyVfFAunbXgTekF6XqDPQUf1nq9aZ\n")
.append("lMvo4vlaLDKBkhG5HJE/pIa0iB+RMZLS0GhxsIWerEDmYdHKM25o\n").append("-----END RSA PRIVATE KEY-----\n")
.toString();
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"),
"myUser", key, null, "happy bear");
"cluster-1.mydomain.com", null, "x86", "rhel", "redhat", "5.3", false, 22, "hadoop",
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",
"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",
"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
public void testNodesParse() throws Exception {

View File

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

View File

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

View File

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

View File

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

View File

@ -24,6 +24,7 @@ import org.jclouds.compute.domain.NodeMetadata;
import org.jclouds.sshj.config.SshjSshClientModule;
import org.testng.annotations.Test;
import com.google.common.collect.ImmutableMap;
import com.google.inject.Module;
/**
@ -40,6 +41,13 @@ public class CloudSigmaComputeServiceLiveTest extends BaseComputeServiceLiveTest
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) {
// hostname is not predictable based on node metadata
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.testng.annotations.Test;
import com.google.common.collect.ImmutableMap;
import com.google.inject.Module;
/**
@ -50,6 +51,12 @@ public class DeltacloudComputeServiceLiveTest extends BaseComputeServiceLiveTest
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 {
@SuppressWarnings("unused")
RestContext<DeltacloudClient, DeltacloudAsyncClient> tmContext = new ComputeServiceContextFactory()

View File

@ -89,6 +89,11 @@ public class RunningInstanceToNodeMetadata implements Function<RunningInstance,
if (instance == null || instance.getId() == null)
return null;
NodeMetadataBuilder builder = new NodeMetadataBuilder();
builder = buildInstance(instance, builder);
return builder.build();
}
protected NodeMetadataBuilder buildInstance(RunningInstance instance, NodeMetadataBuilder builder) {
builder.providerId(instance.getId());
builder.id(instance.getRegion() + "/" + instance.getId());
String group = getGroupForInstance(instance);
@ -116,8 +121,7 @@ public class RunningInstanceToNodeMetadata implements Function<RunningInstance,
} catch (UncheckedExecutionException e) {
logger.debug("error getting image for %s: %s", regionAndName, e);
}
return builder.build();
return builder;
}
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 java.util.Arrays;
import java.util.Map;
import java.util.Set;
import org.jclouds.javax.annotation.Nullable;
import org.jclouds.compute.options.TemplateOptions;
import org.jclouds.domain.Credentials;
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.UnmapDeviceNamed;
import org.jclouds.io.Payload;
import org.jclouds.javax.annotation.Nullable;
import org.jclouds.scriptbuilder.domain.Statement;
import org.jclouds.util.Preconditions2;
@ -42,11 +42,11 @@ import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Iterables;
/**
* Contains options supported in the {@code ComputeService#runNode} operation on the "ec2" provider.
* <h2>
* Usage</h2> The recommended way to instantiate a EC2TemplateOptions object is to statically import
* EC2TemplateOptions.* and invoke a static creation method followed by an instance mutator (if
* needed):
* Contains options supported in the {@code ComputeService#runNode} operation on
* the "ec2" provider. <h2>
* Usage</h2> The recommended way to instantiate a EC2TemplateOptions object is
* to statically import EC2TemplateOptions.* and invoke a static creation method
* followed by an instance mutator (if needed):
* <p/>
* <code>
* 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();
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
@ -370,14 +377,6 @@ public class EC2TemplateOptions extends TemplateOptions implements Cloneable {
return EC2TemplateOptions.class.cast(super.runScript(script));
}
/**
* {@inheritDoc}
*/
@Override
public EC2TemplateOptions withMetadata() {
return EC2TemplateOptions.class.cast(super.withMetadata());
}
/**
* {@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
* implicit group
* {@inheritDoc}
*/
@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() {
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() {
return keyPair;

View File

@ -52,6 +52,7 @@ import org.jclouds.sshj.config.SshjSshClientModule;
import org.testng.annotations.Test;
import com.google.common.base.Predicate;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSortedSet;
import com.google.common.collect.Iterables;
import com.google.common.collect.Sets;
@ -73,6 +74,14 @@ public class EC2ComputeServiceLiveTest extends BaseComputeServiceLiveTest {
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")
public void testImagesResolveCorrectly() {
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.testng.annotations.Test;
import com.google.common.collect.ImmutableMap;
import com.google.inject.Module;
/**
@ -40,6 +41,13 @@ public class ElasticStackComputeServiceLiveTest extends BaseComputeServiceLiveTe
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
public void testOptionToNotBlock() {
// start call is blocking anyway.

View File

@ -19,6 +19,7 @@
package org.jclouds.openstack.nova.compute.strategy;
import static com.google.common.base.Preconditions.checkNotNull;
import static org.jclouds.openstack.nova.options.CreateServerOptions.Builder.withMetadata;
import java.util.Map;
@ -53,7 +54,8 @@ public class NovaCreateNodeWithGroupEncodedIntoName implements CreateNodeWithGro
@Override
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()));
return serverToNodeMetadata.apply(from);
}

View File

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

View File

@ -50,6 +50,7 @@ import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeoutException;
import net.schmizz.sshj.userauth.UserAuthException;
import org.jclouds.compute.ComputeServiceContext;
import org.jclouds.compute.ComputeServiceContextFactory;
import org.jclouds.compute.RunNodesException;
@ -352,13 +353,6 @@ public class NovaComputeServiceLiveTest extends ComputeBase {
//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 {
for (Image image : computeService.listImages()) {
assert image.getProviderId() != null : image;

View File

@ -19,6 +19,7 @@
package org.jclouds.vcloud.compute.options;
import java.util.Arrays;
import java.util.Map;
import org.jclouds.compute.options.TemplateOptions;
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();
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
public VCloudTemplateOptions withMetadata() {
return VCloudTemplateOptions.class.cast(super.withMetadata());
public VCloudTemplateOptions userMetadata(Map<String, String> userMetadata) {
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
@ -317,7 +334,7 @@ public class VCloudTemplateOptions extends TemplateOptions implements Cloneable
+ ", ipAddressAllocationMode=" + ipAddressAllocationMode + ", inboundPorts="
+ Arrays.toString(inboundPorts) + ", privateKey=" + (privateKey != null) + ", publicKey="
+ (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.testng.annotations.Test;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import com.google.inject.Module;
@ -40,7 +41,7 @@ import com.google.inject.Module;
*
* @author Adrian Cole
*/
@Test(groups = "live", enabled = true, sequential = true)
@Test(groups = "live", enabled = true, singleThreaded = true)
public class VCloudComputeServiceLiveTest extends BaseComputeServiceLiveTest {
public VCloudComputeServiceLiveTest() {
@ -52,6 +53,13 @@ public class VCloudComputeServiceLiveTest extends BaseComputeServiceLiveTest {
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 {
@SuppressWarnings("unused")
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 java.util.Arrays;
import java.util.Map;
import org.jclouds.compute.options.TemplateOptions;
import org.jclouds.io.Payload;
import org.jclouds.util.Preconditions2;
/**
* Contains options supported in the {@code ComputeService#runNode} operation on the
* "trmk-vcloudexpress" provider. <h2>
* Usage</h2> The recommended way to instantiate a TerremarkVCloudTemplateOptions object is to
* statically import TerremarkVCloudTemplateOptions.* and invoke a static creation method followed
* Contains options supported in the {@code ComputeService#runNode} operation on
* the "trmk-vcloudexpress" provider. <h2>
* Usage</h2> The recommended way to instantiate a
* TerremarkVCloudTemplateOptions object is to statically import
* TerremarkVCloudTemplateOptions.* and invoke a static creation method followed
* by an instance mutator (if needed):
* <p/>
* <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();
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
@ -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
* already defined. for example, our option inboundPorts normally creates ingress rules
* accordingly but if we notice you've specified securityGroups, we do not mess with rules at all
* special thing is that we do assume if you are passing groups that you have
* everything you need already defined. for example, our option inboundPorts
* normally creates ingress rules accordingly but if we notice you've
* specified securityGroups, we do not mess with rules at all
*
* @see TemplateOptions#inboundPorts
*/
@ -241,15 +251,23 @@ public class TerremarkVCloudTemplateOptions extends TemplateOptions implements C
}
/**
* @see TemplateOptions#withMetadata
* @see TemplateOptions#userMetadata
*/
@Override
public TerremarkVCloudTemplateOptions withMetadata() {
return TerremarkVCloudTemplateOptions.class.cast(super.withMetadata());
public TerremarkVCloudTemplateOptions userMetadata(Map<String, String> userMetadata) {
return TerremarkVCloudTemplateOptions.class.cast(super.userMetadata(userMetadata));
}
/**
* @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() {
return keyPair;
@ -295,7 +313,7 @@ public class TerremarkVCloudTemplateOptions extends TemplateOptions implements C
return "TerremarkVCloudTemplateOptions [keyPair=" + keyPair + ", noKeyPair=" + noKeyPair + ", inboundPorts="
+ Arrays.toString(inboundPorts) + ", privateKey=" + (privateKey != null) + ", publicKey="
+ (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.util.Arrays;
import java.util.Map;
import java.util.Set;
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.collect.ImmutableSet;
import com.google.common.collect.Maps;
/**
* Contains options supported in the {@code ComputeService#runNodesWithTag} operation. <h2>
* Usage</h2> The recommended way to instantiate a TemplateOptions object is to statically import
* TemplateOptions.* and invoke a static creation method followed by an instance mutator (if
* needed):
* Contains options supported in the {@code ComputeService#runNodesWithTag}
* operation. <h2>
* Usage</h2> The recommended way to instantiate a TemplateOptions object is to
* statically import TemplateOptions.* and invoke a static creation method
* followed by an instance mutator (if needed):
* <p/>
* <code>
* import static org.jclouds.compute.options.TemplateOptions.Builder.*;
@ -71,8 +74,8 @@ public class TemplateOptions extends RunScriptOptions implements Cloneable {
to.authorizePublicKey(this.getPublicKey());
if (this.getPort() != -1)
to.blockOnPort(this.getPort(), this.getSeconds());
if (this.isIncludeMetadata())
to.withMetadata();
if (this.getUserMetadata().size() > 0)
to.userMetadata(this.getUserMetadata());
if (this.getTags().size() > 0)
to.tags(getTags());
if (!this.shouldBlockUntilRunning())
@ -266,19 +269,34 @@ public class TemplateOptions extends RunScriptOptions implements Cloneable {
throw new IllegalArgumentException("privateKey is immutable");
}
@Override
public boolean isIncludeMetadata() {
return delegate.isIncludeMetadata();
}
@Override
public TemplateOptions runScript(byte[] script) {
throw new IllegalArgumentException("script is immutable");
}
@Override
public TemplateOptions withMetadata() {
throw new IllegalArgumentException("metadata is immutable");
public Set<String> getTags() {
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 boolean includeMetadata;
protected boolean blockUntilRunning = true;
protected Map<String, String> userMetadata = Maps.newLinkedHashMap();
public int[] getInboundPorts() {
return inboundPorts;
}
@ -317,10 +335,6 @@ public class TemplateOptions extends RunScriptOptions implements Cloneable {
return publicKey;
}
public boolean isIncludeMetadata() {
return includeMetadata;
}
/**
* @see TemplateOptions#blockUntilRunning(boolean)
*/
@ -334,7 +348,9 @@ public class TemplateOptions extends RunScriptOptions implements Cloneable {
/**
* <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 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
* prologue, so no #!/bin/bash required, path set up, etc
* This script will be executed as the root user upon system startup. This
* script gets a prologue, so no #!/bin/bash required, path set up, etc
*
*/
public TemplateOptions runScript(Statement script) {
@ -442,11 +458,6 @@ public class TemplateOptions extends RunScriptOptions implements Cloneable {
return this;
}
public TemplateOptions withMetadata() {
this.includeMetadata = true;
return this;
}
public static class Builder extends org.jclouds.compute.options.RunScriptOptions.Builder {
public static TemplateOptions nameTask(String name) {
@ -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 #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 #authorizePublicKey(Payload)
@ -576,9 +589,20 @@ public class TemplateOptions extends RunScriptOptions implements Cloneable {
return options.authorizePublicKey(rsaKey);
}
public static TemplateOptions withDetails() {
/**
* @see TemplateOptions#userMetadata(Map)
*/
public static TemplateOptions userMetadata(Map<String, String> userMetadata) {
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) {
@ -592,8 +616,8 @@ public class TemplateOptions extends RunScriptOptions implements Cloneable {
public String toString() {
return "[inboundPorts=" + Arrays.toString(inboundPorts) + ", privateKey=" + (privateKey != null) + ", publicKey="
+ (publicKey != null) + ", runScript=" + (script != null) + ", blockUntilRunning=" + blockUntilRunning
+ ", blockOnComplete=" + blockOnComplete + ", port:seconds=" + port + ":" + seconds
+ ", metadata/details: " + includeMetadata + "]";
+ ", blockOnComplete=" + blockOnComplete + ", port:seconds=" + port + ":" + seconds + ", userMetadata: "
+ userMetadata + "]";
}
/**
@ -613,14 +637,43 @@ public class TemplateOptions extends RunScriptOptions implements Cloneable {
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
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + (blockUntilRunning ? 1231 : 1237);
result = prime * result + Arrays.hashCode(inboundPorts);
result = prime * result + (includeMetadata ? 1231 : 1237);
result = prime * result + port;
result = prime * result + ((userMetadata == null) ? 0 : userMetadata.hashCode());
result = prime * result + ((privateKey == null) ? 0 : privateKey.hashCode());
result = prime * result + ((publicKey == null) ? 0 : publicKey.hashCode());
result = prime * result + ((script == null) ? 0 : script.hashCode());
@ -641,7 +694,10 @@ public class TemplateOptions extends RunScriptOptions implements Cloneable {
return false;
if (!Arrays.equals(inboundPorts, other.inboundPorts))
return false;
if (includeMetadata != other.includeMetadata)
if (userMetadata == null) {
if (other.userMetadata != null)
return false;
} else if (!userMetadata.equals(other.userMetadata))
return false;
if (port != other.port)
return false;

View File

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

View File

@ -50,11 +50,11 @@ import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.Collection;
import java.util.Map;
import java.util.Map.Entry;
import java.util.NoSuchElementException;
import java.util.Properties;
import java.util.Set;
import java.util.SortedSet;
import java.util.Map.Entry;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
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.Predicates;
import com.google.common.base.Supplier;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Iterables;
import com.google.inject.Guice;
@ -531,7 +532,8 @@ public abstract class BaseComputeServiceLiveTest {
assertEquals(toDestroy, destroyed.size());
for (NodeMetadata node : filter(client.listNodesDetailsMatching(all()), inGroup(group))) {
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 {
ImmutableMap<String, String> userMetadata = ImmutableMap.<String, String> of("Name", group);
long startSeconds = currentTimeMillis();
NodeMetadata node = getOnlyElement(client.createNodesInGroup(group, 1, inboundPorts(22, 8080).blockOnPort(22,
300)));
NodeMetadata node = getOnlyElement(client.createNodesInGroup(group, 1,
inboundPorts(22, 8080).blockOnPort(22, 300)
.userMetadata(userMetadata)));
final String nodeId = node.getId();
long createSeconds = (currentTimeMillis() - startSeconds) / 1000;
checkUserMetadataInNodeEquals(node, userMetadata);
getAnonymousLogger().info(
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" */)
public void testTemplateOptions() throws Exception {
TemplateOptions options = new TemplateOptions().withMetadata();
Template t = client.templateBuilder().smallest().options(options).build();
assert t.getOptions().isIncludeMetadata() : "The metadata option should be 'true' " + "for the created template";
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);
}
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.util.Map;
import com.google.common.collect.ImmutableMap;
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) {
this.userMetadata = checkNotNull(userMetadata, "userMetadata");
this.userMetadata = ImmutableMap.copyOf(checkNotNull(userMetadata, "userMetadata"));
return this;
}
}

View File

@ -19,6 +19,7 @@
package org.jclouds.aws.ec2.compute;
import static com.google.common.base.Preconditions.checkState;
import static com.google.common.collect.Iterables.transform;
import java.util.Map;
import java.util.Map.Entry;
@ -34,12 +35,16 @@ import org.jclouds.Constants;
import org.jclouds.aws.ec2.AWSEC2Client;
import org.jclouds.aws.ec2.domain.PlacementGroup;
import org.jclouds.aws.ec2.domain.PlacementGroup.State;
import org.jclouds.aws.util.AWSUtils;
import org.jclouds.collect.Memoized;
import org.jclouds.compute.ComputeServiceContext;
import org.jclouds.compute.RunNodesException;
import org.jclouds.compute.callables.RunScriptOnNode;
import org.jclouds.compute.domain.Hardware;
import org.jclouds.compute.domain.Image;
import org.jclouds.compute.domain.NodeMetadata;
import org.jclouds.compute.domain.NodeMetadataBuilder;
import org.jclouds.compute.domain.Template;
import org.jclouds.compute.domain.TemplateBuilder;
import org.jclouds.compute.internal.PersistNodeCredentials;
import org.jclouds.compute.options.TemplateOptions;
@ -62,9 +67,12 @@ import org.jclouds.scriptbuilder.functions.InitAdminAccess;
import org.jclouds.util.Preconditions2;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Function;
import com.google.common.base.Predicate;
import com.google.common.base.Supplier;
import com.google.common.cache.Cache;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Iterables;
/**
* @author Adrian Cole
@ -91,7 +99,8 @@ public class AWSEC2ComputeService extends EC2ComputeService {
RunScriptOnNode.Factory runScriptOnNodeFactory, InitAdminAccess initAdminAccess,
PersistNodeCredentials persistNodeCredentials, Timeouts timeouts,
@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("DELETED") Predicate<PlacementGroup> placementGroupDeleted) {
super(context, credentialStore, images, sizes, locations, listNodesStrategy, getNodeMetadataStrategy,
@ -104,6 +113,50 @@ public class AWSEC2ComputeService extends EC2ComputeService {
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
void deletePlacementGroup(String region, String 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 java.util.Arrays;
import java.util.Map;
import java.util.Set;
import org.jclouds.javax.annotation.Nullable;
import org.jclouds.aws.ec2.options.RequestSpotInstancesOptions;
import org.jclouds.compute.options.TemplateOptions;
import org.jclouds.domain.Credentials;
import org.jclouds.ec2.compute.options.EC2TemplateOptions;
import org.jclouds.ec2.domain.BlockDeviceMapping;
import org.jclouds.io.Payload;
import org.jclouds.javax.annotation.Nullable;
import org.jclouds.scriptbuilder.domain.Statement;
import org.jclouds.util.Preconditions2;
@ -40,11 +40,11 @@ import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Iterables;
/**
* Contains options supported in the {@code ComputeService#runNode} operation on the "ec2" provider.
* <h2>
* Usage</h2> The recommended way to instantiate a AWSEC2TemplateOptions object is to statically
* import AWSEC2TemplateOptions.* and invoke a static creation method followed by an instance
* mutator (if needed):
* Contains options supported in the {@code ComputeService#runNode} operation on
* the "ec2" provider. <h2>
* Usage</h2> The recommended way to instantiate a AWSEC2TemplateOptions object
* is to statically import AWSEC2TemplateOptions.* and invoke a static creation
* method followed by an instance mutator (if needed):
* <p/>
* <code>
* import static org.jclouds.aws.ec2.compute.options.AWSEC2TemplateOptions.Builder.*;
@ -175,10 +175,6 @@ public class AWSEC2TemplateOptions extends EC2TemplateOptions implements Cloneab
return groupIds;
}
public void setGroupIds(Set<String> groupIds) {
this.groupIds = groupIds;
}
public static class Builder {
/**
@ -344,14 +340,6 @@ public class AWSEC2TemplateOptions extends EC2TemplateOptions implements Cloneab
return options.authorizePublicKey(rsaKey);
}
/**
* @see TemplateOptions#withDetails
*/
public static AWSEC2TemplateOptions withDetails() {
AWSEC2TemplateOptions options = new AWSEC2TemplateOptions();
return options.withMetadata();
}
/**
* @see TemplateOptions#spotPrice
*/
@ -375,6 +363,22 @@ public class AWSEC2TemplateOptions extends EC2TemplateOptions implements Cloneab
AWSEC2TemplateOptions options = new AWSEC2TemplateOptions();
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
@ -387,6 +391,22 @@ public class AWSEC2TemplateOptions extends EC2TemplateOptions implements Cloneab
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}
*/
@ -530,14 +550,6 @@ public class AWSEC2TemplateOptions extends EC2TemplateOptions implements Cloneab
return AWSEC2TemplateOptions.class.cast(super.runScript(script));
}
/**
* {@inheritDoc}
*/
@Override
public AWSEC2TemplateOptions withMetadata() {
return AWSEC2TemplateOptions.class.cast(super.withMetadata());
}
/**
* {@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() {
return placementGroup;

View File

@ -66,4 +66,8 @@ public class AWSRunningInstanceToNodeMetadata extends RunningInstanceToNodeMetad
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;
import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.collect.Iterables.transform;
import java.util.Map;
@ -50,7 +51,6 @@ import org.jclouds.logging.Logger;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Function;
import com.google.common.cache.Cache;
import com.google.common.collect.Iterables;
/**
*
@ -72,8 +72,7 @@ public class AWSEC2CreateNodesInGroupThenAddToSet extends EC2CreateNodesInGroupT
AWSEC2Client client,
Provider<TemplateBuilder> templateBuilderProvider,
CreateKeyPairPlacementAndSecurityGroupsAsNeededAndReturnRunOptions createKeyPairAndSecurityGroupsAsNeededAndReturncustomize,
AWSEC2InstancePresent instancePresent,
Function<RunningInstance, NodeMetadata> runningInstanceToNodeMetadata,
AWSEC2InstancePresent instancePresent, Function<RunningInstance, NodeMetadata> runningInstanceToNodeMetadata,
Cache<RunningInstance, Credentials> instanceToCredentials, Map<String, Credentials> credentialStore,
ComputeUtils utils, SpotInstanceRequestToAWSRunningInstance spotConverter) {
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,
spotPrice, spec, options);
return Iterables.transform(client.getSpotInstanceServices().requestSpotInstancesInRegion(region, spotPrice,
count, spec, options), spotConverter);
return addTagsToInstancesInRegion(
template.getOptions().getUserMetadata(),
transform(
client.getSpotInstanceServices().requestSpotInstancesInRegion(region, spotPrice, count, spec,
options), spotConverter), region);
} 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) {
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 vpcId;
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) {
this.securityGroupIdToNames = ImmutableMap.copyOf(checkNotNull(securityGroupIdToNames,
@ -231,7 +243,7 @@ public class AWSRunningInstance extends RunningInstance {
instanceState, instanceType, ipAddress, kernelId, keyName, launchTime, availabilityZone,
virtualizationType, platform, privateDnsName, privateIpAddress, ramdiskId, reason, rootDeviceType,
rootDeviceName, ebsBlockDevices, monitoringState, placementGroup, productCodes, subnetId,
spotInstanceRequestId, vpcId);
spotInstanceRequestId, vpcId, tags);
}
}
@ -247,6 +259,7 @@ public class AWSRunningInstance extends RunningInstance {
@Nullable
private final String vpcId;
private final Map<String, String> securityGroupIdToNames;
private final Map<String, String> tags;
protected AWSRunningInstance(String region, Map<String, String> securityGroupIdToNames, String amiLaunchIndex,
String dnsName, String imageId, String instanceId, InstanceState instanceState, String instanceType,
@ -254,7 +267,7 @@ public class AWSRunningInstance extends RunningInstance {
String virtualizationType, String platform, String privateDnsName, String privateIpAddress, String ramdiskId,
String reason, RootDeviceType rootDeviceType, String rootDeviceName, Map<String, BlockDevice> ebsBlockDevices,
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,
instanceType, ipAddress, kernelId, keyName, launchTime, availabilityZone, virtualizationType, platform,
privateDnsName, privateIpAddress, ramdiskId, reason, rootDeviceType, rootDeviceName, ebsBlockDevices);
@ -266,6 +279,7 @@ public class AWSRunningInstance extends RunningInstance {
this.vpcId = vpcId;
this.securityGroupIdToNames = ImmutableMap.<String, String> copyOf(checkNotNull(securityGroupIdToNames,
"securityGroupIdToNames"));
this.tags = ImmutableMap.<String, String> copyOf(checkNotNull(tags, "tags"));
}
public Map<String, String> getSecurityGroupIdToNames() {
@ -317,6 +331,13 @@ public class AWSRunningInstance extends RunningInstance {
return subnetId;
}
/**
* tags that are present in the instance
*/
public Map<String, String> getTags() {
return tags;
}
@Override
public int hashCode() {
final int prime = 31;
@ -326,6 +347,7 @@ public class AWSRunningInstance extends RunningInstance {
result = prime * result + ((spotInstanceRequestId == null) ? 0 : spotInstanceRequestId.hashCode());
result = prime * result + ((subnetId == null) ? 0 : subnetId.hashCode());
result = prime * result + ((vpcId == null) ? 0 : vpcId.hashCode());
result = prime * result + ((tags == null) ? 0 : tags.hashCode());
return result;
}
@ -363,6 +385,11 @@ public class AWSRunningInstance extends RunningInstance {
return false;
} else if (!vpcId.equals(other.vpcId))
return false;
if (tags == null) {
if (other.tags != null)
return false;
} else if (!tags.equals(other.tags))
return false;
return true;
}
@ -375,7 +402,8 @@ public class AWSRunningInstance extends RunningInstance {
+ ", platform=" + platform + ", launchTime=" + launchTime + ", rootDeviceName=" + rootDeviceName
+ ", rootDeviceType=" + rootDeviceType + ", ebsBlockDevices=" + ebsBlockDevices + ", monitoringState="
+ 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;
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 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 Date validFrom;
private Date validUntil;
private Map<String, String> tags = Maps.newLinkedHashMap();
public Builder clear() {
this.region = null;
@ -69,6 +74,7 @@ public class SpotInstanceRequest implements Comparable<SpotInstanceRequest> {
this.type = null;
this.validFrom = null;
this.validUntil = null;
tags = Maps.newLinkedHashMap();
return this;
}
@ -77,6 +83,16 @@ public class SpotInstanceRequest implements Comparable<SpotInstanceRequest> {
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) {
this.availabilityZoneGroup = availabilityZoneGroup;
return this;
@ -155,7 +171,7 @@ public class SpotInstanceRequest implements Comparable<SpotInstanceRequest> {
public SpotInstanceRequest build() {
return new SpotInstanceRequest(region, availabilityZoneGroup, launchedAvailabilityZone, createTime, faultCode,
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 Date validFrom;
private final Date validUntil;
private final Map<String, String> tags;
public SpotInstanceRequest(String region, String availabilityZoneGroup, @Nullable String launchedAvailabilityZone,
Date createTime, String faultCode, String faultMessage, String instanceId, String launchGroup,
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.availabilityZoneGroup = availabilityZoneGroup;
this.launchedAvailabilityZone = launchedAvailabilityZone;
@ -238,6 +255,7 @@ public class SpotInstanceRequest implements Comparable<SpotInstanceRequest> {
this.type = checkNotNull(type, "type");
this.validFrom = validFrom;
this.validUntil = validUntil;
this.tags = ImmutableMap.<String, String> copyOf(checkNotNull(tags, "tags"));
}
/**
@ -307,6 +325,13 @@ public class SpotInstanceRequest implements Comparable<SpotInstanceRequest> {
return validUntil;
}
/**
* tags that are present in the instance
*/
public Map<String, String> getTags() {
return tags;
}
@Override
public int hashCode() {
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 + ((validFrom == null) ? 0 : validFrom.hashCode());
result = prime * result + ((validUntil == null) ? 0 : validUntil.hashCode());
result = prime * result + ((tags == null) ? 0 : tags.hashCode());
return result;
}
@ -410,6 +436,11 @@ public class SpotInstanceRequest implements Comparable<SpotInstanceRequest> {
return false;
} else if (!validUntil.equals(other.validUntil))
return false;
if (tags == null) {
if (other.tags != null)
return false;
} else if (!tags.equals(other.tags))
return false;
return true;
}
@ -420,7 +451,7 @@ public class SpotInstanceRequest implements Comparable<SpotInstanceRequest> {
+ faultMessage + ", instanceId=" + instanceId + ", launchGroup=" + launchGroup + ", launchSpecification="
+ launchSpecification + ", productDescription=" + productDescription + ", id=" + id + ", spotPrice="
+ spotPrice + ", state=" + state + ", type=" + type + ", validFrom=" + validFrom + ", validUntil="
+ validUntil + "]";
+ validUntil + ", tags=" + tags + "]";
}
@Override

View File

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

View File

@ -18,7 +18,7 @@
*/
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;
@ -34,10 +34,7 @@ import com.google.common.collect.Sets;
*/
public class TagFilters {
public static enum FilterName {
KEY,
RESOURCE_ID,
RESOURCE_TYPE,
VALUE;
KEY, RESOURCE_ID, RESOURCE_TYPE, VALUE;
public String value() {
return CaseFormat.UPPER_UNDERSCORE.to(CaseFormat.LOWER_HYPHEN, name());
@ -58,22 +55,7 @@ public class TagFilters {
}
public static enum ResourceType {
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;
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;
public String value() {
return CaseFormat.UPPER_UNDERSCORE.to(CaseFormat.LOWER_HYPHEN, name());
@ -301,7 +283,8 @@ public class TagFilters {
private void putAll(FilterName key, Iterable<?> 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());
} else {
// Add the values, to a new set if required

View File

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

View File

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

View File

@ -48,6 +48,7 @@ import org.jclouds.rest.RestContextFactory;
import org.jclouds.scriptbuilder.domain.Statements;
import org.testng.annotations.Test;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.ImmutableSortedSet;
import com.google.common.collect.Iterables;
@ -66,8 +67,15 @@ public class AWSEC2ComputeServiceLiveTest extends EC2ComputeServiceLiveTest {
group = "ec2";
}
// aws-ec2 supports userMetadata
@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 {
AWSSecurityGroupClient securityGroupClient = AWSEC2Client.class.cast(context.getProviderSpecificContext().getApi())
.getSecurityGroupServices();
@ -84,6 +92,9 @@ public class AWSEC2ComputeServiceLiveTest extends EC2ComputeServiceLiveTest {
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).spotPrice(0.3f);
@ -113,6 +124,9 @@ public class AWSEC2ComputeServiceLiveTest extends EC2ComputeServiceLiveTest {
Set<? extends NodeMetadata> nodes = client.createNodesInGroup(group, 1, options);
NodeMetadata first = Iterables.get(nodes, 0);
checkUserMetadataInNodeEquals(first, userMetadata);
assert first.getCredentials() != 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",
new BlockDevice("vol-5829fc32", Attachment.Status.ATTACHED, dateService
.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")
.instanceState(InstanceState.RUNNING).privateDnsName("ip-10-212-185-8.ec2.internal").dnsName(
"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(
"paravirtual").build());
assertEquals(parser.apply(Iterables.get(contents, 0)), new NodeMetadataBuilder().state(NodeState.RUNNING).group(
"zkclustertest").hostname("ip-10-212-81-7").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").build());
assertEquals(
parser.apply(Iterables.get(contents, 0)).toString(),
new NodeMetadataBuilder().state(NodeState.RUNNING).group("zkclustertest").hostname("ip-10-212-81-7")
.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(
"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(

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.MonitoringState;
import org.jclouds.aws.ec2.domain.SpotInstanceRequest;
import org.jclouds.aws.ec2.functions.SpotInstanceRequestToAWSRunningInstance;
import org.jclouds.date.internal.SimpleDateFormatDateService;
import org.jclouds.ec2.domain.InstanceState;
import org.testng.annotations.Test;
@ -34,40 +33,51 @@ import org.testng.annotations.Test;
*
* @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")
public class SpotInstanceRequestToAWSRunningInstanceTest {
public void testConvert() {
SpotInstanceRequest input = SpotInstanceRequest.builder().region("us-east-1").id("sir-228e6406")
.spotPrice(0.001f).type(SpotInstanceRequest.Type.ONE_TIME).state(SpotInstanceRequest.State.OPEN)
SpotInstanceRequest input = SpotInstanceRequest
.builder()
.region("us-east-1")
.id("sir-228e6406")
.spotPrice(0.001f)
.type(SpotInstanceRequest.Type.ONE_TIME)
.state(SpotInstanceRequest.State.OPEN)
.launchSpecification(
LaunchSpecification.builder().imageId("ami-595a0a1c").securityGroupName("default").instanceType(
"m1.large").mapNewVolumeToDevice("/dev/sda1", 1, true).mapEBSSnapshotToDevice(
"/dev/sda2", "snap-1ea27576", 1, true).mapEphemeralDeviceToDevice("/dev/sda3", "vre1")
.monitoringEnabled(false).build()).createTime(
new SimpleDateFormatDateService().iso8601DateParse("2011-03-08T03:30:36.000Z"))
.productDescription("Linux/UNIX").build();
LaunchSpecification.builder().imageId("ami-595a0a1c").securityGroupName("default")
.instanceType("m1.large").mapNewVolumeToDevice("/dev/sda1", 1, true)
.mapEBSSnapshotToDevice("/dev/sda2", "snap-1ea27576", 1, true)
.mapEphemeralDeviceToDevice("/dev/sda3", "vre1").monitoringEnabled(false).build())
.createTime(new SimpleDateFormatDateService().iso8601DateParse("2011-03-08T03:30:36.000Z"))
.productDescription("Linux/UNIX").tag("foo", "bar").build();
assertEquals(new SpotInstanceRequestToAWSRunningInstance().apply(input), AWSRunningInstance.builder().region(
"us-east-1").instanceId("sir-228e6406").spotInstanceRequestId("sir-228e6406").instanceState(
InstanceState.PENDING).imageId("ami-595a0a1c").groupId("default").instanceType("m1.large")
assertEquals(
new SpotInstanceRequestToAWSRunningInstance().apply(input),
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());
}
public void testConvertWhenNotOpenReturnsNull() {
assertEquals(new SpotInstanceRequestToAWSRunningInstance().apply(SpotInstanceRequest.builder()
.region("us-east-1").id("sir-228e6406").type(SpotInstanceRequest.Type.ONE_TIME).state(
SpotInstanceRequest.State.ACTIVE).build()), null);
assertEquals(
new SpotInstanceRequestToAWSRunningInstance().apply(SpotInstanceRequest.builder().region("us-east-1")
.id("sir-228e6406").type(SpotInstanceRequest.Type.ONE_TIME).state(SpotInstanceRequest.State.ACTIVE)
.build()), null);
assertEquals(new SpotInstanceRequestToAWSRunningInstance().apply(SpotInstanceRequest.builder()
.region("us-east-1").id("sir-228e6406").type(SpotInstanceRequest.Type.ONE_TIME).state(
SpotInstanceRequest.State.CANCELLED).build()), null);
assertEquals(
new SpotInstanceRequestToAWSRunningInstance().apply(SpotInstanceRequest.builder().region("us-east-1")
.id("sir-228e6406").type(SpotInstanceRequest.Type.ONE_TIME)
.state(SpotInstanceRequest.State.CANCELLED).build()), null);
assertEquals(new SpotInstanceRequestToAWSRunningInstance().apply(SpotInstanceRequest.builder()
.region("us-east-1").id("sir-228e6406").type(SpotInstanceRequest.Type.ONE_TIME).state(
SpotInstanceRequest.State.UNRECOGNIZED).build()), null);
assertEquals(
new SpotInstanceRequestToAWSRunningInstance().apply(SpotInstanceRequest.builder().region("us-east-1")
.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;
import static com.google.common.base.Preconditions.*;
import static com.google.common.collect.Iterables.*;
import static org.testng.Assert.*;
import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.collect.Iterables.getOnlyElement;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertNotNull;
import java.util.Properties;
import java.util.Set;
@ -53,7 +54,7 @@ import com.google.inject.Module;
*
* @author grkvlt@apache.org
*/
@Test(groups = "live", sequential = true)
@Test(groups = "live", singleThreaded = true)
public class TagClientLiveTest {
private TagClient client;

View File

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

View File

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

View File

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

View File

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

View File

@ -18,20 +18,24 @@
*/
package org.jclouds.gogrid.compute.options;
import java.util.Map;
import org.jclouds.compute.ComputeService;
import org.jclouds.compute.options.TemplateOptions;
import org.jclouds.io.Payload;
/**
* Contains options supported by the {@link ComputeService#createNodesInGroup(String, int, TemplateOptions)}
* and {@link ComputeService#runNodesWithTag(String, int, TemplateOptions)} operations on
* the <em>gogrid</em> provider.
* Contains options supported by the
* {@link ComputeService#createNodesInGroup(String, int, TemplateOptions)} and
* {@link ComputeService#runNodesWithTag(String, int, TemplateOptions)}
* operations on the <em>gogrid</em> provider.
*
* <h2>Usage</h2>
* The recommended way to instantiate a {@link GoGridTemplateOptions} object is to statically
* import {@code GoGridTemplateOptions.*} and invoke a static creation method followed by an
* instance mutator (if needed):
* <h2>Usage</h2> The recommended way to instantiate a
* {@link GoGridTemplateOptions} object is to statically import
* {@code GoGridTemplateOptions.*} and invoke a static creation method followed
* by an instance mutator (if needed):
* <p>
*
* <pre>
* import static org.jclouds.compute.options.GoGridTemplateOptions.Builder.*;
* 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();
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
public GoGridTemplateOptions withMetadata() {
return GoGridTemplateOptions.class.cast(super.withMetadata());
public GoGridTemplateOptions userMetadata(Map<String, String> userMetadata) {
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.testng.annotations.Test;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Iterables;
import com.google.inject.Module;
@ -56,6 +57,13 @@ public class GoGridComputeServiceLiveTest extends BaseComputeServiceLiveTest {
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) {
// hostname is not predictable based on node metadata
}

View File

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

View File

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

View File

@ -19,9 +19,12 @@
package org.jclouds.slicehost.compute;
import org.jclouds.compute.BaseComputeServiceLiveTest;
import org.jclouds.compute.domain.NodeMetadata;
import org.jclouds.sshj.config.SshjSshClientModule;
import org.testng.annotations.Test;
import com.google.common.collect.ImmutableMap;
/**
*
* Generally disabled, as it incurs higher fees.
@ -39,6 +42,12 @@ public class SlicehostComputeServiceLiveTest extends BaseComputeServiceLiveTest
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)
public void testSuspendResume() throws Exception {
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.checkNotNull;
import java.util.Map;
import org.jclouds.compute.ComputeService;
import org.jclouds.compute.options.TemplateOptions;
import org.jclouds.io.Payload;
@ -31,12 +33,13 @@ import com.google.common.net.InternetDomainName;
/**
* Contains options supported by the
* {@link ComputeService#createNodesInGroup(String, int, TemplateOptions)} and
* {@link ComputeService#runNodesWithTag(String, int, TemplateOptions)} operations on the
* <em>gogrid</em> provider.
* {@link ComputeService#runNodesWithTag(String, int, TemplateOptions)}
* operations on the <em>gogrid</em> provider.
*
* <h2>Usage</h2> The recommended way to instantiate a {@link SoftLayerTemplateOptions} object is to
* statically import {@code SoftLayerTemplateOptions.*} and invoke a static creation method followed
* by an instance mutator (if needed):
* <h2>Usage</h2> The recommended way to instantiate a
* {@link SoftLayerTemplateOptions} object is to statically import
* {@code SoftLayerTemplateOptions.*} and invoke a static creation method
* followed by an instance mutator (if needed):
* <p>
*
* <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
* a public suffix!
* will replace the default domain used when ordering virtual guests. Note
* this needs to contain a public suffix!
*
* @see VirtualGuestClient#orderVirtualGuest
* @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();
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
public SoftLayerTemplateOptions withMetadata() {
return SoftLayerTemplateOptions.class.cast(super.withMetadata());
public SoftLayerTemplateOptions userMetadata(Map<String, String> userMetadata) {
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.testng.annotations.Test;
import com.google.common.collect.ImmutableMap;
import com.google.inject.Module;
/**
@ -66,6 +67,13 @@ public class TerremarkECloudComputeServiceLiveTest extends BaseComputeServiceLiv
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
protected Template buildTemplate(TemplateBuilder 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.testng.annotations.Test;
import com.google.common.collect.ImmutableMap;
/**
*
*
* @author Adrian Cole
*/
@Test(groups = "live", enabled = true, sequential = true)
@Test(groups = "live", enabled = true, singleThreaded = true)
public class TerremarkVCloudExpressComputeServiceLiveTest extends BaseComputeServiceLiveTest {
public TerremarkVCloudExpressComputeServiceLiveTest() {
provider = "trmk-vcloudexpress";
@ -60,6 +62,13 @@ public class TerremarkVCloudExpressComputeServiceLiveTest extends BaseComputeSer
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
public void testListImages() throws Exception {
for (Image image : client.listImages()) {

View File

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