fixed merge issues after pull from jclouds/master

This commit is contained in:
Kedar Dave 2011-05-18 11:06:08 -05:00
commit 4445c16112
359 changed files with 9714 additions and 5578 deletions

View File

@ -2,7 +2,7 @@
<!--
Copyright (C) 2010 Cloud Conscious, LLC. <info@cloudconscious.com>
Copyright (C) 2011 Cloud Conscious, LLC. <info@cloudconscious.com>
====================================================================
Licensed under the Apache License, Version 2.0 (the "License");
@ -28,9 +28,12 @@
<version>1.0-SNAPSHOT</version>
<relativePath>../../project/pom.xml</relativePath>
</parent>
<groupId>org.jclouds.api</groupId>
<artifactId>atmos</artifactId>
<name>jclouds atmos components</name>
<packaging>bundle</packaging>
<properties>
<test.initializer>org.jclouds.atmos.blobstore.integration.AtmosStorageTestInitializer</test.initializer>
<test.atmos.endpoint>https://accesspoint.atmos.com</test.atmos.endpoint>
@ -38,6 +41,7 @@
<test.atmos.identity>FIXME</test.atmos.identity>
<test.atmos.credential>FIXME</test.atmos.credential>
</properties>
<dependencies>
<dependency>
<groupId>org.jclouds</groupId>
@ -126,4 +130,20 @@
</profile>
</profiles>
<build>
<plugins>
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
<configuration>
<instructions>
<Bundle-SymbolicName>${project.artifactId}</Bundle-SymbolicName>
<Export-Package>org.jclouds.atmos.*;version="${project.version}"</Export-Package>
<Import-Package>org.jclouds.*;version="${project.version}",*</Import-Package>
</instructions>
</configuration>
</plugin>
</plugins>
</build>
</project>

View File

@ -65,6 +65,8 @@ Here are the properties:
* description - optional; long description of this node
* note this is not yet in jclouds NodeMetadata
* hostname - name or ip address to contact the node on
* location_id - optional; correlates to a ZONE-scoped Location
* note that if present for one node, must be present for all
* os_arch - ex. x86
* os_family - must conform to org.jclouds.compute.domain.OsFamily in lower-hyphen format
ex. rhel, ubuntu, centos, debian, amzn-linux
@ -96,6 +98,7 @@ nodes:
name: cluster-1
description: accounting analytics cluster
hostname: cluster-1.mydomain.com
location_id: virginia
os_arch: x86
os_family: rhel
os_description: redhat with CDH

View File

@ -28,9 +28,12 @@
<version>1.0-SNAPSHOT</version>
<relativePath>../../project/pom.xml</relativePath>
</parent>
<groupId>org.jclouds.api</groupId>
<artifactId>byon</artifactId>
<name>jclouds bring your own node provider</name>
<packaging>bundle</packaging>
<properties>
<test.byon.endpoint>file://c:/test.txt</test.byon.endpoint>
<test.byon.sudo-password> </test.byon.sudo-password>
@ -81,7 +84,7 @@
<dependency>
<groupId>org.yaml</groupId>
<artifactId>snakeyaml</artifactId>
<version>1.6</version>
<version>1.8</version>
</dependency>
</dependencies>
@ -120,4 +123,20 @@
</profile>
</profiles>
<build>
<plugins>
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
<configuration>
<instructions>
<Bundle-SymbolicName>${project.artifactId}</Bundle-SymbolicName>
<Export-Package>org.jclouds.byon.*;version="${project.version}"</Export-Package>
<Import-Package>org.jclouds.*;version="${project.version}",*</Import-Package>
</instructions>
</configuration>
</plugin>
</plugins>
</build>
</project>

View File

@ -20,60 +20,170 @@ package org.jclouds.byon;
import java.net.URI;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import com.google.common.base.Objects;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
/**
*
* @author Adrian Cole
*/
public class Node {
// public due to snakeyaml
public Node() {
public static Builder builder() {
return new Builder();
}
public Node(String id, String name, String description, String hostname, String osArch, String osFamily,
String osDescription, String osVersion, String group, List<String> tags, String username,
String credential, URI credentialUrl, String sudo_password) {
public static class Builder {
private String id;
private String name;
private String description;
private String hostname;
private String locationId;
private String osArch;
private String osFamily;
private String osDescription;
private String osVersion;
private boolean os64Bit;
private String group;
private Set<String> tags = ImmutableSet.of();
private String username;
private String credential;
private URI credentialUrl;
private String sudoPassword;
public Builder id(String id) {
this.id = id;
return this;
}
public Builder name(String name) {
this.name = name;
return this;
}
public Builder description(String description) {
this.description = description;
return this;
}
public Builder hostname(String hostname) {
this.hostname = hostname;
return this;
}
public Builder locationId(String locationId) {
this.locationId = locationId;
return this;
}
public Builder osArch(String osArch) {
this.osArch = osArch;
return this;
}
public Builder osFamily(String osFamily) {
this.osFamily = osFamily;
return this;
}
public Builder osDescription(String osDescription) {
this.osDescription = osDescription;
return this;
}
public Builder osVersion(String osVersion) {
this.osVersion = osVersion;
return this;
}
public Builder os64Bit(boolean os64Bit) {
this.os64Bit = os64Bit;
return this;
}
public Builder group(String group) {
this.group = group;
return this;
}
public Builder tags(Iterable<String> tags) {
this.tags = ImmutableSet.copyOf(tags);
return this;
}
public Builder username(String username) {
this.username = username;
return this;
}
public Builder credential(String credential) {
this.credential = credential;
return this;
}
public Builder credentialUrl(URI credentialUrl) {
this.credentialUrl = credentialUrl;
return this;
}
public Builder sudoPassword(String sudoPassword) {
this.sudoPassword = sudoPassword;
return this;
}
public Node build() {
return new Node(id, name, description, hostname, locationId, osArch, osFamily, osDescription, osVersion,
os64Bit, group, tags, 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, String group,
Iterable<String> tags, String username, String credential, URI credentialUrl, String sudoPassword) {
this.id = id;
this.name = name;
this.description = description;
this.hostname = hostname;
this.os_arch = osArch;
this.os_family = osFamily;
this.os_description = osDescription;
this.os_version = osVersion;
this.locationId = locationId;
this.osArch = osArch;
this.osFamily = osFamily;
this.osDescription = osDescription;
this.osVersion = osVersion;
this.os64Bit = os64Bit;
this.group = group;
this.tags = ImmutableList.copyOf(tags);
this.tags = ImmutableSet.copyOf(tags);
this.username = username;
this.credential = credential;
this.credential_url = credentialUrl != null ? credentialUrl.toASCIIString() : null;
this.sudo_password = sudo_password;
this.credentialUrl = credentialUrl;
this.sudoPassword = sudoPassword;
}
// public due to snakeyaml
public String id;
public String name;
public String description;
public String hostname;
public String os_arch;
public String os_family;
public String os_description;
public String os_version;
public String group;
public List<String> tags;
public String username;
public String credential;
public String credential_url;
public String sudo_password;
private final String id;
private final String name;
private final String description;
private final String hostname;
private final String locationId;
private final String osArch;
private final String osFamily;
private final String osDescription;
private final String osVersion;
private final boolean os64Bit;
private final String group;
private final Set<String> tags;
private final String username;
private final String credential;
private final URI credentialUrl;
private final String sudoPassword;
public String getId() {
return id;
}
public String getLocationId() {
return locationId;
}
public String getName() {
return name;
}
@ -91,19 +201,23 @@ public class Node {
}
public String getOsArch() {
return os_arch;
return osArch;
}
public String getOsFamily() {
return os_family;
return osFamily;
}
public String getOsDescription() {
return os_description;
return osDescription;
}
public String getOsVersion() {
return os_version;
return osVersion;
}
public boolean isOs64Bit() {
return os64Bit;
}
public Set<String> getTags() {
@ -122,7 +236,11 @@ public class Node {
}
public URI getCredentialUrl() {
return credential_url != null ? URI.create(credential_url) : null;
return credentialUrl;
}
public String getSudoPassword() {
return sudoPassword;
}
@Override
@ -130,10 +248,6 @@ public class Node {
return Objects.hashCode(id);
}
public String getSudoPassword() {
return sudo_password;
}
@Override
public boolean equals(Object that) {
if (that == null)
@ -144,10 +258,11 @@ public class Node {
@Override
public String toString() {
return Objects.toStringHelper(this).add("id", id).add("name", name).add("description", description).add(
"hostname", hostname).add("osArch", os_arch).add("osFamily", os_family).add("osDescription",
os_description).add("osVersion", os_version).add("group", group).add("tags", tags).add("username",
username).add("hasCredential", credential != null || credential_url != null).add("hasSudoPassword",
sudo_password != null).toString();
"locationId", locationId).add("hostname", hostname).add("osArch", osArch).add("osFamily", osFamily).add(
"osDescription", osDescription).add("osVersion", osVersion).add("os64Bit", os64Bit).add("group", group)
.add("tags", tags).add("username", username).add("hasCredential",
credential != null || credentialUrl != null).add("hasSudoPassword", sudoPassword != null)
.toString();
}
}

View File

@ -25,7 +25,7 @@ import java.util.Map;
import javax.inject.Singleton;
import org.jclouds.byon.Node;
import org.jclouds.byon.functions.NodesFromYaml;
import org.jclouds.byon.functions.NodesFromYamlStream;
import org.jclouds.byon.internal.BYONComputeServiceAdapter;
import org.jclouds.byon.suppliers.NodesParsedFromSupplier;
import org.jclouds.byon.suppliers.SupplyFromProviderURIOrNodesProperty;
@ -44,7 +44,7 @@ import com.google.inject.TypeLiteral;
*
* @author Adrian Cole
*/
@SuppressWarnings( { "rawtypes", "unchecked" })
@SuppressWarnings("unchecked")
@SingleThreaded
public class BYONComputeServiceContextModule extends
JCloudsNativeComputeServiceAdapterContextModule<Supplier, Supplier> {
@ -53,7 +53,6 @@ public class BYONComputeServiceContextModule extends
super(Supplier.class, Supplier.class, BYONComputeServiceAdapter.class);
}
@SuppressWarnings("unchecked")
@Provides
@Singleton
Supplier provideApi(Supplier<Map<String, Node>> in) {
@ -73,7 +72,7 @@ public class BYONComputeServiceContextModule extends
}).to(SupplyFromProviderURIOrNodesProperty.class);
// TODO make this somehow overridable via user request
bind(new TypeLiteral<Function<InputStream, Map<String, Node>>>() {
}).to(NodesFromYaml.class);
}).to(NodesFromYamlStream.class);
}
}

View File

@ -16,13 +16,25 @@
* limitations under the License.
* ====================================================================
*/
package org.jclouds.cloudstack.parse;
package org.jclouds.byon.config;
import static java.lang.annotation.ElementType.TYPE;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;
import com.google.common.annotations.Beta;
/**
* designates the module configures a {@code Map<String, Node>}
*
* @author Adrian Cole
*
*/
public abstract class BaseItemParserTest<T> extends BaseParserTest<T, T> {
@Beta
@Retention(RUNTIME)
@Target(TYPE)
public @interface ConfiguresNodeStore {
}

View File

@ -0,0 +1,92 @@
/**
*
* Copyright (C) 2011 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* ====================================================================
*/
package org.jclouds.byon.config;
import java.io.InputStream;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import javax.inject.Singleton;
import org.jclouds.byon.Node;
import org.jclouds.byon.domain.YamlNode;
import org.jclouds.collect.TransformingMap;
import org.jclouds.io.CopyInputStreamInputSupplierMap;
import com.google.common.annotations.Beta;
import com.google.common.base.Function;
import com.google.common.io.InputSupplier;
import com.google.inject.AbstractModule;
import com.google.inject.Provides;
import com.google.inject.TypeLiteral;
/**
*
* @author Adrian Cole
*/
@ConfiguresNodeStore
@Beta
public class YamlNodeStoreModule extends AbstractModule {
private static final Map<String, InputSupplier<InputStream>> BACKING = new ConcurrentHashMap<String, InputSupplier<InputStream>>();
private final Map<String, InputStream> backing;
public YamlNodeStoreModule(Map<String, InputStream> backing) {
this.backing = backing;
}
public YamlNodeStoreModule() {
this(null);
}
@Override
protected void configure() {
bind(new TypeLiteral<Function<YamlNode, InputStream>>() {
}).toInstance(org.jclouds.byon.domain.YamlNode.yamlNodeToInputStream);
bind(new TypeLiteral<Function<InputStream, YamlNode>>() {
}).toInstance(org.jclouds.byon.domain.YamlNode.inputStreamToYamlNode);
bind(new TypeLiteral<Function<Node, YamlNode>>() {
}).toInstance(org.jclouds.byon.domain.YamlNode.nodeToYamlNode);
bind(new TypeLiteral<Function<YamlNode, Node>>() {
}).toInstance(org.jclouds.byon.domain.YamlNode.toNode);
if (backing != null) {
bind(new TypeLiteral<Map<String, InputStream>>() {
}).toInstance(backing);
} else {
bind(new TypeLiteral<Map<String, InputSupplier<InputStream>>>() {
}).toInstance(BACKING);
bind(new TypeLiteral<Map<String, InputStream>>() {
}).to(new TypeLiteral<CopyInputStreamInputSupplierMap>() {
});
}
}
@Provides
@Singleton
protected Map<String, Node> provideNodeStore(Map<String, YamlNode> backing,
Function<Node, YamlNode> yamlSerializer, Function<YamlNode, Node> yamlDeserializer) {
return new TransformingMap<String, YamlNode, Node>(backing, yamlDeserializer, yamlSerializer);
}
@Provides
@Singleton
protected Map<String, YamlNode> provideYamlStore(Map<String, InputStream> backing,
Function<YamlNode, InputStream> yamlSerializer, Function<InputStream, YamlNode> yamlDeserializer) {
return new TransformingMap<String, InputStream, YamlNode>(backing, yamlDeserializer, yamlSerializer);
}
}

View File

@ -0,0 +1,199 @@
/**
*
* Copyright (C) 2011 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* ====================================================================
*/
package org.jclouds.byon.domain;
import java.io.InputStream;
import java.net.URI;
import java.util.List;
import org.jclouds.byon.Node;
import org.jclouds.util.Strings2;
import org.yaml.snakeyaml.DumperOptions;
import org.yaml.snakeyaml.Loader;
import org.yaml.snakeyaml.Yaml;
import org.yaml.snakeyaml.constructor.Constructor;
import com.google.common.base.Function;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Lists;
import com.google.common.collect.ImmutableMap.Builder;
import com.google.common.io.Closeables;
/**
* Serializes to the following
*
* <pre>
* id: cluster-1
* name: cluster-1
* description: xyz
* hostname: cluster-1.mydomain.com
* location_id: virginia
* os_arch: x86
* os_family: linux
* os_description: redhat
* os_version: 5.3
* os_64bit: 5.3
* group: hadoop
* tags:
* - vanilla
* username: kelvin
* credential: password_or_rsa
* or
* credential_url: password_or_rsa_file ex. resource:///id_rsa will get the classpath /id_rsa; file://path/to/id_rsa
* sudo_password: password
* </pre>
*
* @author Kelvin Kakugawa
* @author Adrian Cole
*/
public class YamlNode {
public String id;
public String name;
public String description;
public String hostname;
public String location_id;
public String os_arch;
public String os_family;
public String os_description;
public String os_version;
public boolean os_64bit;
public String group;
public List<String> tags = Lists.newArrayList();
public String username;
public String credential;
public String credential_url;
public String sudo_password;
public static Function<YamlNode, Node> toNode = new Function<YamlNode, Node>() {
@Override
public Node apply(YamlNode arg0) {
if (arg0 == null)
return null;
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)
.tags(arg0.tags).username(arg0.username).credential(arg0.credential).credentialUrl(
arg0.credential_url != null ? URI.create(arg0.credential_url) : null).sudoPassword(
arg0.sudo_password).build();
}
};
public Node toNode() {
return toNode.apply(this);
}
public static Function<InputStream, YamlNode> inputStreamToYamlNode = new Function<InputStream, YamlNode>() {
@Override
public YamlNode apply(InputStream in) {
if (in == null)
return null;
// note that snakeyaml also throws nosuchmethod error when you use the non-deprecated
// constructor
try {
return (YamlNode) new Yaml(new Loader(new Constructor(YamlNode.class))).load(in);
} finally {
Closeables.closeQuietly(in);
}
}
};
public static YamlNode fromYaml(InputStream in) {
return inputStreamToYamlNode.apply(in);
}
public static Function<YamlNode, InputStream> yamlNodeToInputStream = new Function<YamlNode, InputStream>() {
@Override
public InputStream apply(YamlNode in) {
if (in == null)
return null;
Builder<String, Object> prettier = ImmutableMap.<String, Object> builder();
if (in.id != null)
prettier.put("id", in.id);
if (in.name != null)
prettier.put("name", in.name);
if (in.description != null)
prettier.put("description", in.description);
if (in.hostname != null)
prettier.put("hostname", in.hostname);
if (in.location_id != null)
prettier.put("location_id", in.location_id);
if (in.os_arch != null)
prettier.put("os_arch", in.os_arch);
if (in.os_family != null)
prettier.put("os_family", in.os_family);
if (in.os_description != null)
prettier.put("os_description", in.os_description);
if (in.os_version != null)
prettier.put("os_version", in.os_version);
if (in.os_64bit)
prettier.put("os_64bit", in.os_64bit);
if (in.group != null)
prettier.put("group", in.group);
if (in.tags.size() != 0)
prettier.put("tags", in.tags);
if (in.username != null)
prettier.put("username", in.username);
if (in.credential != null)
prettier.put("credential", in.credential);
if (in.credential_url != null)
prettier.put("credential_url", in.credential_url);
if (in.sudo_password != null)
prettier.put("sudo_password", in.sudo_password);
DumperOptions options = new DumperOptions();
options.setDefaultFlowStyle(DumperOptions.FlowStyle.BLOCK);
return Strings2.toInputStream(new Yaml(options).dump(prettier.build()));
}
};
public InputStream toYaml() {
return yamlNodeToInputStream.apply(this);
}
public static YamlNode fromNode(Node in) {
return nodeToYamlNode.apply(in);
}
public static Function<Node, YamlNode> nodeToYamlNode = new Function<Node, YamlNode>() {
@Override
public YamlNode apply(Node arg0) {
if (arg0 == null)
return null;
YamlNode yaml = new YamlNode();
yaml.id = arg0.getId();
yaml.name = arg0.getName();
yaml.description = arg0.getDescription();
yaml.hostname = arg0.getHostname();
yaml.location_id = arg0.getLocationId();
yaml.os_arch = arg0.getOsArch();
yaml.os_family = arg0.getOsFamily();
yaml.os_description = arg0.getOsDescription();
yaml.os_version = arg0.getOsVersion();
yaml.os_64bit = arg0.isOs64Bit();
yaml.group = arg0.getGroup();
yaml.tags = ImmutableList.copyOf(arg0.getTags());
yaml.username = arg0.getUsername();
yaml.credential = arg0.getCredential();
yaml.credential_url = arg0.getCredentialUrl() != null ? arg0.getCredentialUrl().toASCIIString() : null;
yaml.sudo_password = arg0.getSudoPassword();
return yaml;
}
};
}

View File

@ -24,25 +24,32 @@ import java.io.IOException;
import java.io.InputStream;
import java.net.URI;
import java.util.Map;
import java.util.NoSuchElementException;
import java.util.Set;
import javax.annotation.Resource;
import javax.inject.Inject;
import javax.inject.Named;
import javax.inject.Singleton;
import org.jclouds.byon.Node;
import org.jclouds.collect.Memoized;
import org.jclouds.compute.domain.NodeMetadata;
import org.jclouds.compute.domain.NodeMetadataBuilder;
import org.jclouds.compute.domain.NodeState;
import org.jclouds.compute.domain.OperatingSystemBuilder;
import org.jclouds.compute.domain.OperatingSystem;
import org.jclouds.compute.domain.OsFamily;
import org.jclouds.compute.reference.ComputeServiceConstants;
import org.jclouds.domain.Credentials;
import org.jclouds.domain.Location;
import org.jclouds.logging.Logger;
import org.jclouds.util.Strings2;
import com.google.common.base.Function;
import com.google.common.base.Predicate;
import com.google.common.base.Supplier;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Iterables;
/**
* @author Adrian Cole
@ -50,16 +57,19 @@ import com.google.common.collect.ImmutableSet;
@Singleton
public class NodeToNodeMetadata implements Function<Node, NodeMetadata> {
@Resource
@Named(ComputeServiceConstants.COMPUTE_LOGGER)
protected Logger logger = Logger.NULL;
private final Supplier<Location> location;
private final Supplier<Set<? extends Location>> locations;
private final Map<String, Credentials> credentialStore;
private final Function<URI, InputStream> slurp;
@Inject
NodeToNodeMetadata(Supplier<Location> location, Function<URI, InputStream> slurp,
Map<String, Credentials> credentialStore) {
NodeToNodeMetadata(Supplier<Location> location, @Memoized Supplier<Set<? extends Location>> locations,
Function<URI, InputStream> slurp, Map<String, Credentials> credentialStore) {
this.location = checkNotNull(location, "location");
this.locations = checkNotNull(locations, "locations");
this.credentialStore = checkNotNull(credentialStore, "credentialStore");
this.slurp = checkNotNull(slurp, "slurp");
}
@ -69,10 +79,10 @@ public class NodeToNodeMetadata implements Function<Node, NodeMetadata> {
NodeMetadataBuilder builder = new NodeMetadataBuilder();
builder.ids(from.getId());
builder.name(from.getName());
builder.location(location.get());
builder.location(findLocationWithId(from.getLocationId()));
builder.group(from.getGroup());
// TODO add tags!
builder.operatingSystem(new OperatingSystemBuilder().arch(from.getOsArch()).family(
builder.tags(from.getTags());
builder.operatingSystem(OperatingSystem.builder().arch(from.getOsArch()).family(
OsFamily.fromValue(from.getOsFamily())).description(from.getOsDescription())
.version(from.getOsVersion()).build());
builder.state(NodeState.RUNNING);
@ -99,4 +109,24 @@ public class NodeToNodeMetadata implements Function<Node, NodeMetadata> {
builder.adminPassword(from.getSudoPassword());
return builder.build();
}
private Location findLocationWithId(final String locationId) {
if (locationId == null)
return location.get();
try {
Location location = Iterables.find(locations.get(), new Predicate<Location>() {
@Override
public boolean apply(Location input) {
return input.getId().equals(locationId);
}
});
return location;
} catch (NoSuchElementException e) {
logger.debug("couldn't match instance location %s in: %s", locationId, locations.get());
return location.get();
}
}
}

View File

@ -27,12 +27,14 @@ import java.util.Map;
import javax.inject.Singleton;
import org.jclouds.byon.Node;
import org.jclouds.byon.domain.YamlNode;
import org.yaml.snakeyaml.Loader;
import org.yaml.snakeyaml.TypeDescription;
import org.yaml.snakeyaml.Yaml;
import org.yaml.snakeyaml.constructor.Constructor;
import com.google.common.base.Function;
import com.google.common.collect.Iterables;
import com.google.common.collect.Maps;
/**
@ -44,6 +46,7 @@ import com.google.common.collect.Maps;
* name: cluster-1
* description: xyz
* hostname: cluster-1.mydomain.com
* location_id: virginia
* os_arch: x86
* os_family: linux
* os_description: redhat
@ -59,36 +62,39 @@ import com.google.common.collect.Maps;
* </pre>
*
* @author Kelvin Kakugawa
* @author Adrian Cole
*/
@Singleton
public class NodesFromYaml implements Function<InputStream, Map<String, Node>> {
public class NodesFromYamlStream implements Function<InputStream, Map<String, Node>> {
/**
* Type-safe config class for YAML
*
*/
public static class Config {
public List<Node> nodes;
public List<YamlNode> nodes;
}
@Override
public Map<String, Node> apply(InputStream source) {
Constructor constructor = new Constructor(Config.class);
TypeDescription nodeDesc = new TypeDescription(Node.class);
TypeDescription nodeDesc = new TypeDescription(YamlNode.class);
nodeDesc.putListPropertyType("tags", String.class);
constructor.addTypeDescription(nodeDesc);
TypeDescription configDesc = new TypeDescription(Config.class);
configDesc.putListPropertyType("nodes", Node.class);
configDesc.putListPropertyType("nodes", YamlNode.class);
constructor.addTypeDescription(configDesc);
// note that snakeyaml also throws nosuchmethod error when you use the non-deprecated
// constructor
Yaml yaml = new Yaml(new Loader(constructor));
Config config = (Config) yaml.load(source);
checkState(config != null, "missing config: class");
checkState(config.nodes != null, "missing nodes: collection");
return Maps.uniqueIndex(config.nodes, new Function<Node, String>() {
return Maps.uniqueIndex(Iterables.transform(config.nodes, YamlNode.toNode), new Function<Node, String>() {
public String apply(Node node) {
return node.getId();
}

View File

@ -21,6 +21,7 @@ package org.jclouds.byon.internal;
import static com.google.common.base.Preconditions.checkNotNull;
import java.util.Map;
import java.util.Set;
import javax.inject.Inject;
import javax.inject.Singleton;
@ -34,11 +35,16 @@ import org.jclouds.compute.domain.NodeMetadata;
import org.jclouds.compute.domain.Template;
import org.jclouds.domain.Credentials;
import org.jclouds.domain.Location;
import org.jclouds.domain.LocationBuilder;
import org.jclouds.domain.LocationScope;
import org.jclouds.location.suppliers.JustProvider;
import com.google.common.base.Function;
import com.google.common.base.Predicates;
import com.google.common.base.Supplier;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Iterables;
import com.google.common.collect.ImmutableSet.Builder;
/**
*
@ -59,8 +65,8 @@ public class BYONComputeServiceAdapter implements JCloudsNativeComputeServiceAda
}
@Override
public NodeMetadata createNodeWithGroupEncodedIntoNameThenStoreCredentials(String tag, String name, Template template,
Map<String, Credentials> credentialStore) {
public NodeMetadata createNodeWithGroupEncodedIntoNameThenStoreCredentials(String tag, String name,
Template template, Map<String, Credentials> credentialStore) {
throw new UnsupportedOperationException();
}
@ -79,10 +85,26 @@ public class BYONComputeServiceAdapter implements JCloudsNativeComputeServiceAda
return Iterables.transform(nodes.get().values(), converter);
}
@SuppressWarnings("unchecked")
@Override
public Iterable<Location> listLocations() {
return (Iterable<Location>) locationSupplier.get();
Builder<Location> locations = ImmutableSet.builder();
Location provider = Iterables.getOnlyElement(locationSupplier.get());
Set<String> zones = ImmutableSet.copyOf(Iterables.filter(Iterables.transform(nodes.get().values(),
new Function<Node, String>() {
@Override
public String apply(Node arg0) {
return arg0.getLocationId();
}
}), Predicates.notNull()));
if (zones.size() == 0)
return locations.add(provider).build();
else
for (String zone : zones) {
locations.add(new LocationBuilder().scope(LocationScope.ZONE).id(zone).description(zone).parent(provider)
.build());
}
return locations.build();
}
@Override

View File

@ -18,16 +18,19 @@
*/
package org.jclouds.byon;
import static org.jclouds.byon.functions.NodeToNodeMetadataTest.expectedNodeMetadataFromResource;
import static org.jclouds.byon.functions.NodeToNodeMetadataTest.expectedProviderLocationFromResource;
import static org.jclouds.byon.functions.NodeToNodeMetadataTest.zoneCalled;
import static org.testng.Assert.assertEquals;
import java.net.URI;
import java.util.Map;
import java.util.Properties;
import org.jclouds.byon.functions.NodeToNodeMetadataTest;
import org.jclouds.byon.functions.NodesFromYamlTest;
import org.jclouds.compute.ComputeServiceContext;
import org.jclouds.compute.ComputeServiceContextFactory;
import org.jclouds.domain.Location;
import org.jclouds.ssh.jsch.config.JschSshClientModule;
import org.testng.annotations.Test;
@ -56,6 +59,7 @@ public class BYONComputeServiceTest {
private void assertNodesParse(String endpoint) {
ComputeServiceContext context = null;
try {
Location providerLocation = expectedProviderLocationFromResource(endpoint);
Properties props = new Properties();
props.setProperty("byon.endpoint", endpoint);
@ -69,12 +73,45 @@ public class BYONComputeServiceTest {
.getApi();
assertEquals(supplier.get().size(), context.getComputeService().listNodes().size());
assertEquals(supplier.get(), ImmutableMap.<String, Node> of(NodesFromYamlTest.TEST1.id,
assertEquals(supplier.get(), ImmutableMap.<String, Node> of(NodesFromYamlTest.TEST1.getId(),
NodesFromYamlTest.TEST1));
assertEquals(context.getComputeService().listNodes(), ImmutableSet.of(NodeToNodeMetadataTest
.expectedNodeMetadataFromResource(endpoint)));
assertEquals(context.getComputeService().listNodes(), ImmutableSet
.of(expectedNodeMetadataFromResource(endpoint)));
assertEquals(context.getComputeService().listAssignableLocations(), ImmutableSet.of(providerLocation));
} finally {
if (context != null)
context.close();
}
}
public void testNodesWithLocations() {
ComputeServiceContext context = null;
try {
String endpoint = "file://" + getClass().getResource("/test_location.yaml").getPath();
Properties props = new Properties();
props.setProperty("byon.endpoint", endpoint);
context = new ComputeServiceContextFactory().createContext("byon", "foo", "bar", ImmutableSet
.<Module> of(new JschSshClientModule()), props);
assertEquals(context.getProviderSpecificContext().getEndpoint(), URI.create(endpoint));
@SuppressWarnings("unchecked")
Supplier<Map<String, Node>> supplier = (Supplier<Map<String, Node>>) context.getProviderSpecificContext()
.getApi();
assertEquals(supplier.get().size(), context.getComputeService().listNodes().size());
assertEquals(supplier.get(), ImmutableMap.<String, Node> of(NodesFromYamlTest.TEST2.getId(),
NodesFromYamlTest.TEST2, NodesFromYamlTest.TEST3.getId(), NodesFromYamlTest.TEST3));
Location providerLocation = expectedProviderLocationFromResource(endpoint);
Location virginia = zoneCalled("virginia", providerLocation);
Location maryland = zoneCalled("maryland", providerLocation);
assertEquals(context.getComputeService().listNodes(), ImmutableSet.of(expectedNodeMetadataFromResource(1,
endpoint, virginia), expectedNodeMetadataFromResource(2, endpoint, maryland)));
assertEquals(context.getComputeService().listAssignableLocations(), ImmutableSet.of(virginia, maryland));
} finally {
if (context != null)
context.close();

View File

@ -0,0 +1,163 @@
/**
*
* Copyright (C) 2011 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* ====================================================================
*/
package org.jclouds.byon.config;
import static org.testng.Assert.assertEquals;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import org.jclouds.byon.Node;
import org.jclouds.io.CopyInputStreamInputSupplierMap;
import org.jclouds.util.Strings2;
import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;
import org.yaml.snakeyaml.Yaml;
import com.google.common.io.InputSupplier;
import com.google.inject.Guice;
import com.google.inject.Injector;
import com.google.inject.Key;
import com.google.inject.TypeLiteral;
/**
*
* @author Adrian Cole
*/
@Test(groups = "unit", singleThreaded = true)
public class YamlNodeStoreModuleTest {
Yaml json = createInjector().getInstance(Yaml.class);
@DataProvider(name = "names")
public Object[][] createData() {
return new Object[][] { { "instance1", "bear" }, { "instance2", "apple" }, { "instance2", "francis" },
{ "instance4", "robot" } };
}
@Test(dataProvider = "names")
public void deleteObject(String id, String name) throws InterruptedException, IOException {
Injector injector = createInjector();
Map<String, InputStream> map = getMap(injector);
check(map, getStore(injector), "i-20312", id, name);
}
public void testProvidedMapWithValue() throws IOException {
Map<String, InputStream> map = new CopyInputStreamInputSupplierMap(
new ConcurrentHashMap<String, InputSupplier<InputStream>>());
map.put("test", new ByteArrayInputStream("id: instance1\nname: instancename\n".getBytes()));
checkConsistent(map, getStore(createInjectorWithProvidedMap(map)), "test", "instance1", "instancename");
checkConsistent(map, getStore(createInjectorWithProvidedMap(map)), "test", "instance1", "instancename");
remove(map, getStore(createInjectorWithProvidedMap(map)), "test");
}
public void testProvidedConsistentAcrossRepeatedWrites() throws IOException {
Map<String, InputStream> map = new CopyInputStreamInputSupplierMap(
new ConcurrentHashMap<String, InputSupplier<InputStream>>());
Injector injector = createInjectorWithProvidedMap(map);
assertEquals(injector.getInstance(Key.get(new TypeLiteral<Map<String, InputStream>>() {
})), map);
Map<String, Node> store = getStore(injector);
for (int i = 0; i < 10; i++)
check(map, store, "test" + i, "instance1" + i, "instancename" + i);
}
public void testProvidedConsistentAcrossMultipleInjectors() throws IOException {
Map<String, InputStream> map = new CopyInputStreamInputSupplierMap(
new ConcurrentHashMap<String, InputSupplier<InputStream>>());
put(map, getStore(createInjectorWithProvidedMap(map)), "test", "instance1", "instancename");
checkConsistent(map, getStore(createInjectorWithProvidedMap(map)), "test", "instance1", "instancename");
checkConsistent(map, getStore(createInjectorWithProvidedMap(map)), "test", "instance1", "instancename");
remove(map, getStore(createInjectorWithProvidedMap(map)), "test");
}
public void testDefaultConsistentAcrossMultipleInjectors() throws IOException {
Map<String, InputStream> map = getMap(createInjector());
put(map, getStore(createInjector()), "test", "instance1", "instancename");
checkConsistent(map, getStore(createInjector()), "test", "instance1", "instancename");
checkConsistent(map, getStore(createInjector()), "test", "instance1", "instancename");
remove(map, getStore(createInjector()), "test");
}
protected Map<String, Node> getStore(Injector injector) {
return injector.getInstance(Key.get(new TypeLiteral<Map<String, Node>>() {
}));
}
protected Map<String, InputStream> getMap(Injector injector) {
return injector.getInstance(Key.get(new TypeLiteral<Map<String, InputStream>>() {
}));
}
protected Injector createInjectorWithProvidedMap(Map<String, InputStream> map) {
return Guice.createInjector(new YamlNodeStoreModule(map));
}
protected Injector createInjector() {
return Guice.createInjector(new YamlNodeStoreModule());
}
protected void check(Map<String, InputStream> map, Map<String, Node> store, String key, String id, String name)
throws IOException {
put(map, store, key, id, name);
checkConsistent(map, store, key, id, name);
remove(map, store, key);
}
protected void remove(Map<String, InputStream> map, Map<String, Node> store, String key) {
store.remove(key);
assertEquals(store.size(), 0);
assertEquals(map.size(), 0);
assertEquals(store.get(key), null);
assertEquals(map.get(key), null);
}
protected void checkConsistent(Map<String, InputStream> map, Map<String, Node> store, String key, String id,
String name) throws IOException {
assertEquals(store.size(), 1);
assertEquals(map.size(), 1);
// checkRepeatedRead
assertEquals(store.get(key), Node.builder().id(id).name(name).build());
assertEquals(store.get(key), Node.builder().id(id).name(name).build());
// checkRepeatedRead
checkToYaml(map, key, id, name);
checkToYaml(map, key, id, name);
}
protected void checkToYaml(Map<String, InputStream> map, String key, String id, String name) throws IOException {
assertEquals(Strings2.toStringAndClose(map.get(key)), String.format("id: %s\nname: %s\n", id, name));
}
protected void put(Map<String, InputStream> map, Map<String, Node> store, String key, String id, String name) {
assertEquals(store.size(), 0);
assertEquals(map.size(), 0);
store.put(key, Node.builder().id(id).name(name).build());
}
}

View File

@ -22,12 +22,13 @@ import static org.testng.Assert.assertEquals;
import java.net.URI;
import java.util.Map;
import java.util.Set;
import org.jclouds.byon.suppliers.SupplyFromProviderURIOrNodesProperty;
import org.jclouds.compute.domain.NodeMetadata;
import org.jclouds.compute.domain.NodeMetadataBuilder;
import org.jclouds.compute.domain.NodeState;
import org.jclouds.compute.domain.OperatingSystemBuilder;
import org.jclouds.compute.domain.OperatingSystem;
import org.jclouds.compute.domain.OsFamily;
import org.jclouds.domain.Credentials;
import org.jclouds.domain.Location;
@ -45,31 +46,51 @@ import com.google.common.collect.Maps;
* @author Adrian Cole
*/
public class NodeToNodeMetadataTest {
public static Location expectedLocationFromResource(String resource) {
public static Location expectedProviderLocationFromResource(String resource) {
return new LocationBuilder().scope(LocationScope.PROVIDER).id("byon").description(resource).build();
}
public static NodeMetadata expectedNodeMetadataFromResource(String resource) {
Location location = expectedLocationFromResource(resource);
public static Location zoneCalled(String zone, Location parent) {
return new LocationBuilder().scope(LocationScope.ZONE).id(zone).description(zone).parent(parent).build();
}
return new NodeMetadataBuilder().ids("cluster-1").group("hadoop").name("cluster-1").location(location).state(
NodeState.RUNNING).operatingSystem(
new OperatingSystemBuilder().description("redhat").family(OsFamily.RHEL).arch("x86").version("5.3")
.build()).publicAddresses(ImmutableSet.of("cluster-1.mydomain.com")).credentials(
new Credentials("myUser", NodesFromYamlTest.key)).adminPassword("happy bear").build();
String resource = "location";
Location provider = expectedProviderLocationFromResource(resource);
Map<String, Credentials> credentialStore = Maps.newLinkedHashMap();
NodeToNodeMetadata parser = new NodeToNodeMetadata(Suppliers.ofInstance(provider), Suppliers
.<Set<? extends Location>> ofInstance(ImmutableSet.of(provider, zoneCalled("virginia", provider))),
new SupplyFromProviderURIOrNodesProperty(URI.create("test")), credentialStore);
public static NodeMetadata expectedNodeMetadataFromResource(String resource) {
return expectedNodeMetadataFromResource(resource, expectedProviderLocationFromResource(resource));
}
public static NodeMetadata expectedNodeMetadataFromResource(String resource, Location location) {
return expectedNodeMetadataFromResource(1, resource, location);
}
public static NodeMetadata expectedNodeMetadataFromResource(int id, String resource, Location location) {
return new NodeMetadataBuilder().ids("cluster-" + id).group("hadoop").name("cluster-" + id).location(location)
.state(NodeState.RUNNING).operatingSystem(
OperatingSystem.builder().description("redhat").family(OsFamily.RHEL).arch("x86")
.version("5.3").build()).publicAddresses(
ImmutableSet.of("cluster-" + id + ".mydomain.com")).credentials(
new Credentials("myUser", NodesFromYamlTest.key)).adminPassword("happy bear").build();
}
@Test
public void testNodesParse() throws Exception {
Map<String, Credentials> credentialStore = Maps.newLinkedHashMap();
NodeToNodeMetadata parser = new NodeToNodeMetadata(
Suppliers.ofInstance(expectedLocationFromResource("location")),
new SupplyFromProviderURIOrNodesProperty(URI.create("test")), credentialStore);
assertEquals(parser.apply(NodesFromYamlTest.TEST1), expectedNodeMetadataFromResource("location"));
assertEquals(parser.apply(NodesFromYamlTest.TEST1), expectedNodeMetadataFromResource(resource, provider));
assertEquals(credentialStore, ImmutableMap.of("node#cluster-1", new Credentials("myUser", NodesFromYamlTest.key)));
}
@Test
public void testNodesParseLocation() throws Exception {
assertEquals(parser.apply(NodesFromYamlTest.TEST2), expectedNodeMetadataFromResource(resource, zoneCalled(
"virginia", provider)));
assertEquals(credentialStore, ImmutableMap.of("node#cluster-1", new Credentials("myUser", NodesFromYamlTest.key)));
}
}

View File

@ -41,29 +41,47 @@ public class NodesFromYamlTest {
.toString();
public static final Node TEST1 = new Node("cluster-1", "cluster-1", "accounting analytics cluster",
"cluster-1.mydomain.com", "x86", "rhel", "redhat", "5.3", "hadoop", ImmutableList.of("vanilla"), "myUser",
key, null, "happy bear");
"cluster-1.mydomain.com", null, "x86", "rhel", "redhat", "5.3", false, "hadoop", ImmutableList.of("vanilla"),
"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, "hadoop",
ImmutableList.of("vanilla"), "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, "hadoop",
ImmutableList.of("vanilla"), "myUser", key, null, "happy bear");
@Test
public void testNodesParse() throws Exception {
InputStream is = getClass().getResourceAsStream("/test1.yaml");
NodesFromYaml parser = new NodesFromYaml();
NodesFromYamlStream parser = new NodesFromYamlStream();
assertEquals(parser.apply(is), ImmutableMap.of(TEST1.getId(), TEST1));
}
@Test
public void testNodesParseLocation() throws Exception {
InputStream is = getClass().getResourceAsStream("/test_location.yaml");
NodesFromYamlStream parser = new NodesFromYamlStream();
assertEquals(parser.apply(is), ImmutableMap.of(TEST2.getId(), TEST2, TEST3.getId(), TEST3));
}
@Test
public void testNodesParseWhenCredentialInUrl() throws Exception {
InputStream is = getClass().getResourceAsStream("/test_with_url.yaml");
NodesFromYaml parser = new NodesFromYaml();
NodesFromYamlStream parser = new NodesFromYamlStream();
assertEquals(parser.apply(is), ImmutableMap.of(TEST1.getId(), TEST1));
}
@Test(expectedExceptions = IllegalStateException.class)
public void testMustParseSomething() throws Exception {
new NodesFromYaml().apply(Strings2.toInputStream(""));
new NodesFromYamlStream().apply(Strings2.toInputStream(""));
}
}

View File

@ -18,7 +18,7 @@
*/
package org.jclouds.byon.suppliers;
import org.jclouds.byon.functions.NodesFromYaml;
import org.jclouds.byon.functions.NodesFromYamlStream;
import org.jclouds.util.Strings2;
import org.testng.annotations.Test;
@ -33,7 +33,7 @@ public class NodesParsedFromSupplierTest {
@Test(expectedExceptions = IllegalStateException.class)
public void testMustParseSomething() throws Exception {
new NodesParsedFromSupplier(Suppliers.ofInstance(Strings2.toInputStream("nodes:\n")), new NodesFromYaml()).get();
new NodesParsedFromSupplier(Suppliers.ofInstance(Strings2.toInputStream("nodes:\n")), new NodesFromYamlStream()).get();
}
}

View File

@ -0,0 +1,43 @@
nodes:
- id: cluster-1
name: cluster-1
description: accounting analytics cluster
hostname: cluster-1.mydomain.com
location_id: virginia
os_arch: x86
os_family: rhel
os_description: redhat
os_version: 5.3
group: hadoop
tags:
- vanilla
username: myUser
credential: |
-----BEGIN RSA PRIVATE KEY-----
MIIEowIBAAKCAQEAuzaE6azgUxwESX1rCGdJ5xpdrc1XC311bOGZBCE8NA+CpFh2
u01Vfv68NC4u6LFgdXSY1vQt6hiA5TNqQk0TyVfFAunbXgTekF6XqDPQUf1nq9aZ
lMvo4vlaLDKBkhG5HJE/pIa0iB+RMZLS0GhxsIWerEDmYdHKM25o
-----END RSA PRIVATE KEY-----
sudo_password: happy bear
- id: cluster-2
name: cluster-2
description: accounting analytics cluster
hostname: cluster-2.mydomain.com
location_id: maryland
os_arch: x86
os_family: rhel
os_description: redhat
os_version: 5.3
group: hadoop
tags:
- vanilla
username: myUser
credential: |
-----BEGIN RSA PRIVATE KEY-----
MIIEowIBAAKCAQEAuzaE6azgUxwESX1rCGdJ5xpdrc1XC311bOGZBCE8NA+CpFh2
u01Vfv68NC4u6LFgdXSY1vQt6hiA5TNqQk0TyVfFAunbXgTekF6XqDPQUf1nq9aZ
lMvo4vlaLDKBkhG5HJE/pIa0iB+RMZLS0GhxsIWerEDmYdHKM25o
-----END RSA PRIVATE KEY-----
sudo_password: happy bear

View File

@ -33,6 +33,7 @@
<artifactId>cloudfiles</artifactId>
<name>jcloud cloudfiles api</name>
<description>jclouds components to access an implementation of CloudFiles</description>
<packaging>bundle</packaging>
<properties>
<test.initializer>org.jclouds.cloudfiles.blobstore.integration.CloudFilesTestInitializer</test.initializer>
@ -145,6 +146,21 @@
</profile>
</profiles>
<build>
<plugins>
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
<configuration>
<instructions>
<Bundle-SymbolicName>${project.artifactId}</Bundle-SymbolicName>
<Export-Package>org.jclouds.cloudfiles.*;version="${project.version}"</Export-Package>
<Import-Package>org.jclouds.*;version="${project.version}",*</Import-Package>
</instructions>
</configuration>
</plugin>
</plugins>
</build>
</project>

View File

@ -29,10 +29,12 @@
<version>1.0-SNAPSHOT</version>
<relativePath>../../project/pom.xml</relativePath>
</parent>
<groupId>org.jclouds.api</groupId>
<artifactId>cloudservers</artifactId>
<name>jcloud cloudservers api</name>
<description>jclouds components to access an implementation of CloudServers</description>
<packaging>bundle</packaging>
<properties>
<test.cloudservers.endpoint>https://auth.api.rackspacecloud.com</test.cloudservers.endpoint>
@ -145,6 +147,21 @@
</profile>
</profiles>
<build>
<plugins>
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
<configuration>
<instructions>
<Bundle-SymbolicName>${project.artifactId}</Bundle-SymbolicName>
<Export-Package>org.jclouds.cloudservers.*;version="${project.version}"</Export-Package>
<Import-Package>org.jclouds.*;version="${project.version}",*</Import-Package>
</instructions>
</configuration>
</plugin>
</plugins>
</build>
</project>

View File

@ -34,6 +34,7 @@
<artifactId>deltacloud</artifactId>
<name>jclouds deltacloud core</name>
<description>jclouds components to access deltacloud</description>
<packaging>bundle</packaging>
<!-- bootstrapping: need to fetch the project POM -->
<repositories>
@ -141,4 +142,21 @@
</build>
</profile>
</profiles>
<build>
<plugins>
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
<configuration>
<instructions>
<Bundle-SymbolicName>${project.artifactId}</Bundle-SymbolicName>
<Export-Package>org.jclouds.deltacloud.*;version="${project.version}"</Export-Package>
<Import-Package>org.jclouds.*;version="${project.version}",*</Import-Package>
</instructions>
</configuration>
</plugin>
</plugins>
</build>
</project>

View File

@ -33,6 +33,7 @@
<artifactId>ec2</artifactId>
<name>jcloud ec2 api</name>
<description>jclouds components to access an implementation of EC2</description>
<packaging>bundle</packaging>
<properties>
<!-- when instances are hung, open a ticket and add here -->
@ -142,6 +143,21 @@
</profile>
</profiles>
<build>
<plugins>
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
<configuration>
<instructions>
<Bundle-SymbolicName>${project.artifactId}</Bundle-SymbolicName>
<Export-Package>org.jclouds.ec2.*;version="${project.version}"</Export-Package>
<Import-Package>org.jclouds.*;version="${project.version}",*</Import-Package>
</instructions>
</configuration>
</plugin>
</plugins>
</build>
</project>

View File

@ -25,20 +25,20 @@
(:use (clojure.contrib def core))
(:import org.jclouds.aws.domain.Region
org.jclouds.compute.domain.NodeMetadata
(org.jclouds.aws.ec2.domain Volume Volume$Status Snapshot Snapshot$Status AvailabilityZone)
(org.jclouds.aws.ec2.options DescribeSnapshotsOptions DetachVolumeOptions CreateSnapshotOptions)))
(org.jclouds.ec2.domain Volume Volume$Status Snapshot Snapshot$Status AvailabilityZoneInfo)
(org.jclouds.ec2.options DescribeSnapshotsOptions DetachVolumeOptions CreateSnapshotOptions)))
(defn snapshot?
"Returns true iff the argument is a org.jclouds.aws.ec2.domain.Snapshot."
"Returns true iff the argument is a org.jclouds.ec2.domain.Snapshot."
[s]
(instance? Snapshot s))
(defn volume?
"Returns true iff the argument is a org.jclouds.aws.ec2.domain.Volume."
"Returns true iff the argument is a org.jclouds.ec2.domain.Volume."
[v]
(instance? Volume v))
(defn #^org.jclouds.aws.ec2.services.ElasticBlockStoreClient
(defn #^org.jclouds.ec2.services.ElasticBlockStoreClient
ebs-service
"Returns the synchronous ElasticBlockStoreClient associated with
the specified compute service, or compute/*compute* as bound by with-compute-service."
@ -74,7 +74,7 @@
(str "Can't obtain volume id from argument of type " (class v))))))
(defn volumes
"Returns a set of org.jclouds.aws.ec2.domain.Volume instances corresponding to the
"Returns a set of org.jclouds.ec2.domain.Volume instances corresponding to the
volumes in the specified region (defaulting to your account's default region).
e.g. (with-compute-service [compute] (volumes))
@ -172,7 +172,7 @@
(defn get-zone
[v]
(cond
(instance? AvailabilityZone v) v
(instance? AvailabilityZoneInfo v) (.getZone v)
(instance? NodeMetadata v) (compute/location #^NodeMetadata v)
(string? v) v
(keyword? v) (name v)
@ -225,14 +225,14 @@
(defn create-volume
"Creates a new volume given a set of options:
- one of :zone (keyword, string, or AvailabilityZone) or :node (NodeMetadata)
- one of :zone (keyword, string, or AvailabilityZoneInfo) or :node (NodeMetadata)
- one or both of :snapshot (keyword, string, or Snapshot instance) or :size
(string, keyword, or number)
- :device (string or keyword) provided *only* when you want to attach the new volume to
the :node you specified!
Returns a vector of [created org.jclouds.aws.ec2.domain.Volume,
optional org.jclouds.aws.ec2.domain.Attachment]
Returns a vector of [created org.jclouds.ec2.domain.Volume,
optional org.jclouds.ec2.domain.Attachment]
Note that specifying :node instead of :zone will only attach the created volume
:device is also provided. Otherwise, the node is only used to obtain the desired

View File

@ -22,12 +22,12 @@
:doc "A clojure binding for the jclouds AWS elastic IP address interface."}
org.jclouds.ec2.elastic-ip
(:require (org.jclouds [compute :as compute])
[org.jclouds.aws.ebs :as ebs])
[org.jclouds.ec2.ebs :as ebs])
(:use (clojure.contrib def core))
(:import org.jclouds.compute.domain.NodeMetadata
(org.jclouds.aws.ec2.domain PublicIpInstanceIdPair)))
(org.jclouds.ec2.domain PublicIpInstanceIdPair)))
(defn #^org.jclouds.aws.ec2.services.ElasticIPAddressClient
(defn #^org.jclouds.ec2.services.ElasticIPAddressClient
eip-service
"Returns the synchronous ElasticIPAddressClient associated with
the specified compute service, or compute/*compute* as bound by with-compute-service."

View File

@ -37,6 +37,7 @@ import org.jclouds.Constants;
import org.jclouds.aws.util.AWSUtils;
import org.jclouds.collect.Memoized;
import org.jclouds.compute.ComputeServiceContext;
import org.jclouds.compute.callables.RunScriptOnNode;
import org.jclouds.compute.domain.Hardware;
import org.jclouds.compute.domain.Image;
import org.jclouds.compute.domain.NodeMetadata;
@ -91,14 +92,16 @@ public class EC2ComputeService extends BaseComputeService {
@Named("NODE_RUNNING") Predicate<NodeMetadata> nodeRunning,
@Named("NODE_TERMINATED") Predicate<NodeMetadata> nodeTerminated,
@Named("NODE_SUSPENDED") Predicate<NodeMetadata> nodeSuspended,
InitializeRunScriptOnNodeOrPlaceInBadMap.Factory initScriptRunnerFactory, InitAdminAccess initAdminAccess,
InitializeRunScriptOnNodeOrPlaceInBadMap.Factory initScriptRunnerFactory,
RunScriptOnNode.Factory runScriptOnNodeFactory, InitAdminAccess initAdminAccess,
PersistNodeCredentials persistNodeCredentials, Timeouts timeouts,
@Named(Constants.PROPERTY_USER_THREADS) ExecutorService executor, EC2Client ec2Client,
Map<RegionAndName, KeyPair> credentialsMap, @Named("SECURITY") Map<RegionAndName, String> securityGroupMap) {
super(context, credentialStore, images, sizes, locations, listNodesStrategy, getNodeMetadataStrategy,
runNodesAndAddToSetStrategy, rebootNodeStrategy, destroyNodeStrategy, startNodeStrategy, stopNodeStrategy,
templateBuilderProvider, templateOptionsProvider, nodeRunning, nodeTerminated, nodeSuspended,
initScriptRunnerFactory, initAdminAccess, persistNodeCredentials, timeouts, executor);
initScriptRunnerFactory, initAdminAccess, runScriptOnNodeFactory, persistNodeCredentials, timeouts,
executor);
this.ec2Client = ec2Client;
this.credentialsMap = credentialsMap;
this.securityGroupMap = securityGroupMap;

View File

@ -65,7 +65,7 @@ public class Volume implements Comparable<Volume> {
}
public static enum Status {
CREATING, AVAILABLE, IN_USE, DELETING, UNRECOGNIZED;
CREATING, AVAILABLE, IN_USE, DELETING, ERROR, UNRECOGNIZED;
public String value() {
return CaseFormat.UPPER_UNDERSCORE.to(CaseFormat.LOWER_HYPHEN, name());
}

View File

@ -34,6 +34,7 @@
<artifactId>elasticstack</artifactId>
<name>jclouds elasticstack core</name>
<description>jclouds components to access elasticstack</description>
<packaging>bundle</packaging>
<!-- bootstrapping: need to fetch the project POM -->
<repositories>
@ -147,4 +148,20 @@
</build>
</profile>
</profiles>
<build>
<plugins>
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
<configuration>
<instructions>
<Bundle-SymbolicName>${project.artifactId}</Bundle-SymbolicName>
<Export-Package>org.jclouds.elastichosts.*;version="${project.version}"</Export-Package>
<Import-Package>org.jclouds.*;version="${project.version}",*</Import-Package>
</instructions>
</configuration>
</plugin>
</plugins>
</build>
</project>

View File

@ -33,6 +33,7 @@
<artifactId>eucalyptus</artifactId>
<name>jclouds Eucalyptus api</name>
<description>EC2 implementation based on Eucalyptus</description>
<packaging>bundle</packaging>
<properties>
<test.eucalyptus.endpoint>http://ecc.eucalyptus.com:8773/services/Eucalyptus</test.eucalyptus.endpoint>
@ -136,6 +137,21 @@
</profile>
</profiles>
<build>
<plugins>
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
<configuration>
<instructions>
<Bundle-SymbolicName>${project.artifactId}</Bundle-SymbolicName>
<Export-Package>org.jclouds.eucalyptus.*;version="${project.version}"</Export-Package>
<Import-Package>org.jclouds.*;version="${project.version}",*</Import-Package>
</instructions>
</configuration>
</plugin>
</plugins>
</build>
</project>

View File

@ -33,6 +33,7 @@
<artifactId>filesystem</artifactId>
<name>jcloud filesystem core</name>
<description>jclouds components to access filesystem</description>
<packaging>bundle</packaging>
<dependencies>
<dependency>
@ -72,5 +73,21 @@
<test.initializer>org.jclouds.filesystem.integration.FilesystemTestInitializer</test.initializer>
</properties>
<build>
<plugins>
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
<configuration>
<instructions>
<Bundle-SymbolicName>${project.artifactId}</Bundle-SymbolicName>
<Export-Package>org.jclouds.filesystem.*;version="${project.version}"</Export-Package>
<Import-Package>org.jclouds.*;version="${project.version}",*</Import-Package>
</instructions>
</configuration>
</plugin>
</plugins>
</build>
</project>

View File

@ -33,6 +33,7 @@
<artifactId>nova</artifactId>
<name>jcloud nova api</name>
<description>jclouds components to access an implementation of OpenStack Nova</description>
<packaging>bundle</packaging>
<properties>
@ -96,22 +97,6 @@
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<artifactId>maven-remote-resources-plugin</artifactId>
<version>1.2</version>
<executions>
<execution>
<id>process-remote-resources</id>
<!-- plugin is tuned off due to incorrect work in Eclipse-->
<phase></phase>
</execution>
</executions>
</plugin>
</plugins>
</build>
<profiles>
<profile>
<id>live</id>
@ -175,5 +160,20 @@
</profile>
</profiles>
<build>
<plugins>
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
<configuration>
<instructions>
<Bundle-SymbolicName>${project.artifactId}</Bundle-SymbolicName>
<Export-Package>org.jclouds.openstack.nova.*;version="${project.version}"</Export-Package>
<Import-Package>org.jclouds.*;version="${project.version}",*</Import-Package>
</instructions>
</configuration>
</plugin>
</plugins>
</build>
</project>

View File

@ -66,7 +66,7 @@ import static org.testng.Assert.assertEquals;
* @author Adrian Cole
*/
// NOTE:without testName, this will not call @Before* and fail w/NPE during surefire
@Test(groups = "unit", testName = "NovaAsyncClientTest")
@Test(groups = "unit", singleThreaded = true, testName = "NovaAsyncClientTest")
public class NovaAsyncClientTest extends RestClientTest<NovaAsyncClient> {
private static final Class<? extends ListOptions[]> listOptionsVarargsClass = new ListOptions[]{}.getClass();
private static final Class<? extends CreateServerOptions[]> createServerOptionsVarargsClass = new CreateServerOptions[]{}

View File

@ -33,6 +33,7 @@
<artifactId>s3</artifactId>
<name>jcloud s3 api</name>
<description>jclouds components to access an implementation of S3</description>
<packaging>bundle</packaging>
<properties>
<test.initializer>org.jclouds.s3.blobstore.integration.S3TestInitializer</test.initializer>
@ -143,6 +144,21 @@
</profile>
</profiles>
<build>
<plugins>
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
<configuration>
<instructions>
<Bundle-SymbolicName>${project.artifactId}</Bundle-SymbolicName>
<Export-Package>org.jclouds.s3.*;version="${project.version}"</Export-Package>
<Import-Package>org.jclouds.*;version="${project.version}",*</Import-Package>
</instructions>
</configuration>
</plugin>
</plugins>
</build>
</project>

View File

@ -33,6 +33,7 @@
<artifactId>scality-rs2</artifactId>
<name>jclouds Eucalyptus Walrus api</name>
<description>Simple Storage Service (S3) implementation based on Scality RING RS2</description>
<packaging>bundle</packaging>
<properties>
<test.initializer>org.jclouds.scality.rs2.blobstore.ScalityRS2TestInitializer</test.initializer>
@ -139,6 +140,21 @@
</profile>
</profiles>
<build>
<plugins>
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
<configuration>
<instructions>
<Bundle-SymbolicName>${project.artifactId}</Bundle-SymbolicName>
<Export-Package>org.jclouds.scality.rs2.*;version="${project.version}"</Export-Package>
<Import-Package>org.jclouds.*;version="${project.version}",*</Import-Package>
</instructions>
</configuration>
</plugin>
</plugins>
</build>
</project>

View File

@ -33,6 +33,7 @@
<artifactId>swift</artifactId>
<name>jcloud swift api</name>
<description>jclouds components to access an implementation of OpenStack Swift</description>
<packaging>bundle</packaging>
<properties>
<test.initializer>org.jclouds.openstack.swift.blobstore.integration.SwiftTestInitializer</test.initializer>
@ -143,6 +144,21 @@
</profile>
</profiles>
<build>
<plugins>
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
<configuration>
<instructions>
<Bundle-SymbolicName>${project.artifactId}</Bundle-SymbolicName>
<Export-Package>org.jclouds.openstack.swift.*;version="${project.version}"</Export-Package>
<Import-Package>org.jclouds.*;version="${project.version}",*</Import-Package>
</instructions>
</configuration>
</plugin>
</plugins>
</build>
</project>

View File

@ -32,6 +32,7 @@
<artifactId>vcloud</artifactId>
<name>jcloud vcloud api</name>
<description>jclouds components to access an implementation of VMWare vCloud</description>
<packaging>bundle</packaging>
<properties>
<!-- when instances are hung, open a ticket and add here -->
@ -156,4 +157,20 @@
</profile>
</profiles>
<build>
<plugins>
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
<configuration>
<instructions>
<Bundle-SymbolicName>${project.artifactId}</Bundle-SymbolicName>
<Export-Package>org.jclouds.vcloud.*;version="${project.version}"</Export-Package>
<Import-Package>org.jclouds.*;version="${project.version}",*</Import-Package>
</instructions>
</configuration>
</plugin>
</plugins>
</build>
</project>

View File

@ -32,6 +32,7 @@
<artifactId>vcloudexpress</artifactId>
<name>jcloud vcloudexpress api</name>
<description>jclouds components to access an implementation of VMWare vCloud Express</description>
<packaging>bundle</packaging>
<properties>
<!-- when instances are hung, open a ticket and add here -->
@ -156,4 +157,20 @@
</profile>
</profiles>
<build>
<plugins>
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
<configuration>
<instructions>
<Bundle-SymbolicName>${project.artifactId}</Bundle-SymbolicName>
<Export-Package>org.jclouds.vcloud.*;version="${project.version}"</Export-Package>
<Import-Package>org.jclouds.*;version="${project.version}",*</Import-Package>
</instructions>
</configuration>
</plugin>
</plugins>
</build>
</project>

View File

@ -33,6 +33,7 @@
<artifactId>walrus</artifactId>
<name>jclouds Eucalyptus Walrus api</name>
<description>Simple Storage Service (S3) implementation based on Eucalyptus Walrus</description>
<packaging>bundle</packaging>
<properties>
<test.initializer>org.jclouds.walrus.blobstore.WalrusTestInitializer</test.initializer>
@ -139,6 +140,21 @@
</profile>
</profiles>
<build>
<plugins>
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
<configuration>
<instructions>
<Bundle-SymbolicName>${project.artifactId}</Bundle-SymbolicName>
<Export-Package>org.jclouds.walrus.*;version="${project.version}"</Export-Package>
<Import-Package>org.jclouds.*;version="${project.version}",*</Import-Package>
</instructions>
</configuration>
</plugin>
</plugins>
</build>
</project>

View File

@ -32,6 +32,7 @@
<artifactId>jclouds-blobstore</artifactId>
<name>jclouds blobstore core</name>
<description>jclouds components to access blobstore</description>
<packaging>bundle</packaging>
<scm>
<connection>scm:svn:http://jclouds.googlecode.com/svn/trunk/blobstore</connection>
@ -118,6 +119,18 @@
</excludes>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
<configuration>
<instructions>
<Bundle-SymbolicName>${project.artifactId}</Bundle-SymbolicName>
<Export-Package>org.jclouds.blobstore.*;version="${project.version}"</Export-Package>
<Import-Package>org.jclouds.*;version="${project.version}",*</Import-Package>
<Fragment-Host>jclouds-core;version="${project.version}"</Fragment-Host>
</instructions>
</configuration>
</plugin>
</plugins>
</build>
</project>

View File

@ -32,6 +32,8 @@
<artifactId>aws-common</artifactId>
<name>jclouds Amazon AWS Components Core</name>
<description>jclouds Core components to access Amazon AWS</description>
<packaging>bundle</packaging>
<dependencies>
<dependency>
<groupId>org.jclouds</groupId>
@ -47,4 +49,20 @@
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
<configuration>
<instructions>
<Bundle-SymbolicName>${project.artifactId}</Bundle-SymbolicName>
<Export-Package>org.jclouds.aws.*;version="${project.version}"</Export-Package>
<Import-Package>org.jclouds.*;version="${project.version}",*</Import-Package>
</instructions>
</configuration>
</plugin>
</plugins>
</build>
</project>

View File

@ -2,7 +2,7 @@
<!--
Copyright (C) 2010 Cloud Conscious, LLC. <info@cloudconscious.com>
Copyright (C) 2011 Cloud Conscious, LLC. <info@cloudconscious.com>
====================================================================
Licensed under the Apache License, Version 2.0 (the "License");
@ -32,6 +32,8 @@
<artifactId>azure-common</artifactId>
<name>jclouds Azure Components Core</name>
<description>jclouds Core components to access Azure</description>
<packaging>bundle</packaging>
<dependencies>
<dependency>
<groupId>org.jclouds</groupId>
@ -47,4 +49,20 @@
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
<configuration>
<instructions>
<Bundle-SymbolicName>${project.artifactId}</Bundle-SymbolicName>
<Export-Package>org.jclouds.azure.*;version="${project.version}"</Export-Package>
<Import-Package>org.jclouds.*;version="${project.version}",*</Import-Package>
</instructions>
</configuration>
</plugin>
</plugins>
</build>
</project>

View File

@ -2,7 +2,7 @@
<!--
Copyright (C) 2010 Cloud Conscious, LLC. <info@cloudconscious.com>
Copyright (C) 2011 Cloud Conscious, LLC. <info@cloudconscious.com>
====================================================================
Licensed under the Apache License, Version 2.0 (the "License");
@ -28,10 +28,13 @@
<version>1.0-SNAPSHOT</version>
<relativePath>../../project/pom.xml</relativePath>
</parent>
<groupId>org.jclouds.common</groupId>
<artifactId>openstack-common</artifactId>
<name>jclouds Rackspace Components Core</name>
<description>jclouds Core components to access Rackspace apis</description>
<name>jclouds OpenStack Components Core</name>
<description>jclouds Core components to access OpenStack apis</description>
<packaging>bundle</packaging>
<dependencies>
<dependency>
<groupId>org.jclouds</groupId>
@ -47,4 +50,20 @@
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
<configuration>
<instructions>
<Bundle-SymbolicName>${project.artifactId}</Bundle-SymbolicName>
<Export-Package>org.jclouds.openstack.*;version="${project.version}"</Export-Package>
<Import-Package>org.jclouds.*;version="${project.version}",*</Import-Package>
</instructions>
</configuration>
</plugin>
</plugins>
</build>
</project>

View File

@ -2,7 +2,7 @@
<!--
Copyright (C) 2010 Cloud Conscious, LLC. <info@cloudconscious.com>
Copyright (C) 2011 Cloud Conscious, LLC. <info@cloudconscious.com>
====================================================================
Licensed under the Apache License, Version 2.0 (the "License");
@ -28,10 +28,13 @@
<version>1.0-SNAPSHOT</version>
<relativePath>../../project/pom.xml</relativePath>
</parent>
<groupId>org.jclouds.common</groupId>
<artifactId>trmk-common</artifactId>
<name>common Terremark components</name>
<description>common Terremark components</description>
<packaging>bundle</packaging>
<dependencies>
<dependency>
<groupId>org.jclouds.api</groupId>
@ -91,4 +94,20 @@
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
<configuration>
<instructions>
<Bundle-SymbolicName>${project.artifactId}</Bundle-SymbolicName>
<Export-Package>org.jclouds.vcloud.terremark.*;version="${project.version}"</Export-Package>
<Import-Package>org.jclouds.*;version="${project.version}",*</Import-Package>
</instructions>
</configuration>
</plugin>
</plugins>
</build>
</project>

View File

@ -31,6 +31,7 @@ import javax.inject.Singleton;
import org.jclouds.Constants;
import org.jclouds.collect.Memoized;
import org.jclouds.compute.ComputeServiceContext;
import org.jclouds.compute.callables.RunScriptOnNode;
import org.jclouds.compute.domain.Hardware;
import org.jclouds.compute.domain.Image;
import org.jclouds.compute.domain.NodeMetadata;
@ -77,14 +78,16 @@ public class TerremarkVCloudComputeService extends BaseComputeService {
@Named("NODE_RUNNING") Predicate<NodeMetadata> nodeRunning,
@Named("NODE_TERMINATED") Predicate<NodeMetadata> nodeTerminated,
@Named("NODE_SUSPENDED") Predicate<NodeMetadata> nodeSuspended,
InitializeRunScriptOnNodeOrPlaceInBadMap.Factory initScriptRunnerFactory, InitAdminAccess initAdminAccess,
InitializeRunScriptOnNodeOrPlaceInBadMap.Factory initScriptRunnerFactory,
RunScriptOnNode.Factory runScriptOnNodeFactory, InitAdminAccess initAdminAccess,
PersistNodeCredentials persistNodeCredentials, Timeouts timeouts,
@Named(Constants.PROPERTY_USER_THREADS) ExecutorService executor, CleanupOrphanKeys cleanupOrphanKeys,
ConcurrentMap<OrgAndName, KeyPairCredentials> credentialsMap, NodeMetadataToOrgAndName nodeToOrgAndName) {
super(context, credentialStore, images, sizes, locations, listNodesStrategy, getNodeMetadataStrategy,
runNodesAndAddToSetStrategy, rebootNodeStrategy, destroyNodeStrategy, resumeNodeStrategy,
suspendNodeStrategy, templateBuilderProvider, templateOptionsProvider, nodeRunning, nodeTerminated,
nodeSuspended, initScriptRunnerFactory, initAdminAccess, persistNodeCredentials, timeouts, executor);
nodeSuspended, initScriptRunnerFactory, initAdminAccess, runScriptOnNodeFactory, persistNodeCredentials,
timeouts, executor);
this.cleanupOrphanKeys = cleanupOrphanKeys;
}

View File

@ -28,10 +28,13 @@
<version>1.0-SNAPSHOT</version>
<relativePath>../../project/pom.xml</relativePath>
</parent>
<groupId>org.jclouds.common</groupId>
<artifactId>vcloud-common</artifactId>
<name>common vCloud components</name>
<description>common vCloud components</description>
<packaging>bundle</packaging>
<dependencies>
<dependency>
<groupId>com.jamesmurty.utils</groupId>
@ -82,4 +85,19 @@
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
<configuration>
<instructions>
<Bundle-SymbolicName>${project.artifactId}</Bundle-SymbolicName>
<Export-Package>org.jclouds.vcloud.*;version="${project.version}"</Export-Package>
<Import-Package>org.jclouds.*;version="${project.version}",*</Import-Package>
</instructions>
</configuration>
</plugin>
</plugins>
</build>
</project>

View File

@ -28,7 +28,6 @@ import java.util.regex.Pattern;
import javax.inject.Inject;
import javax.inject.Provider;
import javax.inject.Singleton;
import javax.ws.rs.core.HttpHeaders;
import org.jclouds.http.HttpResponse;
import org.jclouds.http.HttpResponseException;
@ -49,36 +48,35 @@ import com.google.common.base.Function;
*/
@Singleton
public class ParseLoginResponseFromHeaders implements Function<HttpResponse, VCloudSession> {
static final Pattern pattern = Pattern.compile("vcloud-token=([^;]+);.*");
static final Pattern pattern = Pattern.compile("(vcloud-token=)?([^;]+)(;.*)?");
private final ParseSax.Factory factory;
private final Provider<OrgListHandler> orgHandlerProvider;
@Inject
private ParseLoginResponseFromHeaders(Factory factory,
Provider<OrgListHandler> orgHandlerProvider) {
private ParseLoginResponseFromHeaders(Factory factory, Provider<OrgListHandler> orgHandlerProvider) {
this.factory = factory;
this.orgHandlerProvider = orgHandlerProvider;
}
/**
* parses the http response headers to create a new {@link VCloudSession} object.
* parses the http response headers to create a new {@link VCloudSession}
* object.
*/
public VCloudSession apply(HttpResponse from) {
String cookieHeader = checkNotNull(from.getFirstHeaderOrNull(HttpHeaders.SET_COOKIE),
HttpHeaders.SET_COOKIE);
String cookieHeader = checkNotNull(from.getFirstHeaderOrNull("x-vcloud-authorization"), "x-vcloud-authorization");
final Matcher matcher = pattern.matcher(cookieHeader);
boolean matchFound = matcher.find();
try {
if (matchFound) {
final Map<String, ReferenceType> org = factory.create(orgHandlerProvider.get()).parse(
from.getPayload().getInput());
from.getPayload().getInput());
return new VCloudSession() {
@VCloudToken
public String getVCloudToken() {
return matcher.group(1);
return matcher.group(2);
}
@Org
@ -91,6 +89,6 @@ public class ParseLoginResponseFromHeaders implements Function<HttpResponse, VCl
} finally {
releasePayload(from);
}
throw new HttpResponseException("not found ", null, from);
throw new HttpResponseException("x-vcloud-authorization not found ", null, from);
}
}

View File

@ -18,6 +18,7 @@
*/
package org.jclouds.vcloud.xml;
import static org.jclouds.util.SaxUtils.equalsOrSuffix;
import static org.jclouds.vcloud.util.Utils.newReferenceType;
import java.util.List;
@ -271,11 +272,11 @@ public class OrgNetworkHandler extends ParseSax.HandlerWithResult<OrgNetwork> {
this.vmNicId = -1;
} else if (qName.equalsIgnoreCase("ExternalPort")) {
externalPort = Integer.parseInt(currentOrNull());
} else if (qName.equalsIgnoreCase("IxternalIP")) {
} else if (qName.equalsIgnoreCase("InternalIP")) {
internalIP = currentOrNull();
} else if (qName.equalsIgnoreCase("InternalPort")) {
internalPort = Integer.parseInt(currentOrNull());
} else if (qName.equals("NatProtocol")) {
} else if (equalsOrSuffix(qName, "Protocol")) {
natProtocol = NatProtocol.valueOf(currentOrNull());
} else if (qName.equals("PortForwardingRule")) {
natRules.add(new PortForwardingRule(externalIP, externalPort, internalIP, internalPort, natProtocol));

View File

@ -22,8 +22,6 @@ import static org.testng.Assert.assertEquals;
import java.net.URI;
import javax.ws.rs.core.HttpHeaders;
import org.jclouds.http.HttpResponse;
import org.jclouds.http.functions.BaseHandlerTest;
import org.jclouds.io.Payloads;
@ -55,7 +53,7 @@ public class ParseLoginResponseFromHeadersTest extends BaseHandlerTest {
@Test
public void testApply() {
HttpResponse response = new HttpResponse(200, "OK", Payloads.newInputStreamPayload(getClass()
.getResourceAsStream("/orglist.xml")), ImmutableMultimap.<String,String>of(HttpHeaders.SET_COOKIE, "vcloud-token=9er4d061-4bff-48fa-84b1-5da7166764d2; path=/"));
.getResourceAsStream("/orglist.xml")), ImmutableMultimap.<String,String>of("x-vcloud-authorization", "vcloud-token=9er4d061-4bff-48fa-84b1-5da7166764d2; path=/"));
response.getPayload().getContentMetadata().setContentType("Content-Type: application/xml; charset=utf-8");
response.getPayload().getContentMetadata().setContentLength(307l);
@ -69,15 +67,28 @@ public class ParseLoginResponseFromHeadersTest extends BaseHandlerTest {
@Test
public void testApplyBlueLock() {
HttpResponse response = new HttpResponse(200, "OK", Payloads.newInputStreamPayload(getClass()
.getResourceAsStream("/orglist.xml")), ImmutableMultimap.<String,String>of(HttpHeaders.SET_COOKIE,"vcloud-token=c9f232506df9b65d7b7d97b7499eddd7; Domain=.bluelock.com; Path=/") );
.getResourceAsStream("/orglist.xml")), ImmutableMultimap.<String,String>of("x-vcloud-authorization","MUKOJ2HoAfoMmLnHRp4esNb2MtWscCLLhVysnsIsCG0=") );
response.getPayload().getContentMetadata().setContentType("Content-Type: application/xml; charset=utf-8");
response.getPayload().getContentMetadata().setContentLength(307l);
VCloudSession reply = parser.apply(response);
assertEquals(reply.getVCloudToken(), "c9f232506df9b65d7b7d97b7499eddd7");
assertEquals(reply.getVCloudToken(), "MUKOJ2HoAfoMmLnHRp4esNb2MtWscCLLhVysnsIsCG0=");
assertEquals(reply.getOrgs(), ImmutableMap.of("adrian@jclouds.org", new ReferenceTypeImpl("adrian@jclouds.org",
VCloudMediaType.ORG_XML, URI.create("https://services.vcloudexpress.terremark.com/api/v0.8/org/48"))));
}
@Test
public void testApplyVirtacore() {
HttpResponse response = new HttpResponse(200, "OK", Payloads.newInputStreamPayload(getClass()
.getResourceAsStream("/orglist.xml")), ImmutableMultimap.<String,String>of("x-vcloud-authorization","vcloud-token=IPy0w7UGD4lwtdWAK/ZVzfuLK+dztxGRqsOhWqV0i48=") );
response.getPayload().getContentMetadata().setContentType("Content-Type: application/xml; charset=utf-8");
response.getPayload().getContentMetadata().setContentLength(307l);
VCloudSession reply = parser.apply(response);
assertEquals(reply.getVCloudToken(), "IPy0w7UGD4lwtdWAK/ZVzfuLK+dztxGRqsOhWqV0i48=");
assertEquals(reply.getOrgs(), ImmutableMap.of("adrian@jclouds.org", new ReferenceTypeImpl("adrian@jclouds.org",
VCloudMediaType.ORG_XML, URI.create("https://services.vcloudexpress.terremark.com/api/v0.8/org/48"))));
}
}

View File

@ -29,15 +29,11 @@
<version>1.0-SNAPSHOT</version>
<relativePath>../project/pom.xml</relativePath>
</parent>
<artifactId>jclouds-compute</artifactId>
<name>jclouds compute core</name>
<description>jclouds components to access compute providers</description>
<scm>
<connection>scm:svn:http://jclouds.googlecode.com/svn/trunk/compute</connection>
<developerConnection>scm:svn:https://jclouds.googlecode.com/svn/trunk/compute</developerConnection>
<url>http://jclouds.googlecode.com/svn/trunk/compute</url>
</scm>
<packaging>bundle</packaging>
<dependencies>
<dependency>
@ -70,4 +66,21 @@
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
<configuration>
<instructions>
<Bundle-SymbolicName>${project.artifactId}</Bundle-SymbolicName>
<Export-Package>org.jclouds.compute.*;version="${project.version}",org.jclouds.ssh.*;version="${project.version}"</Export-Package>
<Import-Package>!org.jclouds.compute.*;org.jclouds.*;version="${project.version}",*</Import-Package>
<Fragment-Host>jclouds-core;version="${project.version}"</Fragment-Host>
</instructions>
</configuration>
</plugin>
</plugins>
</build>
</project>

View File

@ -69,7 +69,8 @@ Here's an example of creating and running a small linux node in the group webser
[org.jclouds.compute.domain
Template TemplateBuilder ComputeMetadata NodeMetadata Hardware
OsFamily Image]
[org.jclouds.compute.options TemplateOptions]
[org.jclouds.compute.options TemplateOptions RunScriptOptions
RunScriptOptions$Builder]
[org.jclouds.compute.predicates
NodePredicates]
[com.google.common.collect ImmutableSet])
@ -197,7 +198,7 @@ Here's an example of creating and running a small linux node in the group webser
(defn suspend-node
"Suspend a node, given its id."
([id #^ComputeService compute]
([#^ComputeService compute id]
(.suspendNode compute id)))
(defn resume-nodes-matching
@ -208,7 +209,7 @@ Here's an example of creating and running a small linux node in the group webser
(defn resume-node
"Resume a node, given its id."
([id #^ComputeService compute]
([#^ComputeService compute id]
(.resumeNode compute id)))
(defn reboot-nodes-matching
@ -219,7 +220,7 @@ Here's an example of creating and running a small linux node in the group webser
(defn reboot-node
"Reboot a node, given its id."
([id #^ComputeService compute]
([#^ComputeService compute id]
(.rebootNode compute id)))
(defn destroy-nodes-matching
@ -230,9 +231,19 @@ Here's an example of creating and running a small linux node in the group webser
(defn destroy-node
"Destroy a node, given its id."
([id #^ComputeService compute]
([#^ComputeService compute id]
(.destroyNode compute id)))
(defn run-script-on-node
"Run a script on a node"
([#^ComputeService compute id command #^RunScriptOptions options]
(.runScriptOnNode compute id command options)))
(defn run-script-on-nodes-matching
"Run a script on the nodes matching the given predicate"
([#^ComputeService compute pred command #^RunScriptOptions options]
(.runScriptOnNodesMatching compute (to-predicate pred) command options)))
(defmacro state-predicate [node state]
`(= (.getState ~node)
(. org.jclouds.compute.domain.NodeState ~state)))

View File

@ -319,4 +319,40 @@ public interface ComputeService {
Map<? extends NodeMetadata, ExecResponse> runScriptOnNodesMatching(Predicate<NodeMetadata> filter,
Statement runScript, RunScriptOptions options) throws RunScriptOnNodesException;
/**
* Run the script on a specific node
*
* @param id
* node the script is to be executed on
* @param runScript
* statement containing the script to run
* @param options
* nullable options to how to run the script, whether to override credentials
* @return map with node identifiers and corresponding responses
* @throws NoSuchElementException
* if the node is not found
* @throws IllegalStateException
* if the node is not in running state
*
* @see org.jclouds.compute.predicates.NodePredicates#runningWithTag(String)
* @see org.jclouds.scriptbuilder.domain.Statements
*/
ExecResponse runScriptOnNode(String id, Statement runScript, RunScriptOptions options);
/**
* @see #runScriptOnNode(String, Statement, RunScriptOptions)
*/
ExecResponse runScriptOnNode(String id, Statement runScript);
/**
* @see #runScriptOnNode(String, Statement, RunScriptOptions)
* @see org.jclouds.scriptbuilder.domain.Statements#exec
*/
ExecResponse runScriptOnNode(String id, String runScript, RunScriptOptions options);
/**
* @see #runScriptOnNode(String, String, RunScriptOptions)
*/
ExecResponse runScriptOnNode(String id, String runScript);
}

View File

@ -18,6 +18,10 @@
*/
package org.jclouds.compute.domain;
import java.util.Set;
import javax.annotation.Nullable;
import org.jclouds.compute.domain.internal.ComputeMetadataImpl;
import org.jclouds.domain.ResourceMetadata;
@ -30,24 +34,23 @@ import com.google.inject.ImplementedBy;
@ImplementedBy(ComputeMetadataImpl.class)
public interface ComputeMetadata extends ResourceMetadata<ComputeType> {
/**
* Type of the resource, ex node, image, size
*
* @return Type of the resource, ex node, image, size
*/
@Override
public ComputeType getType();
/**
* id of the server within the naming scope it was created. potentially generated by the service.
*
* @return id of the server within the naming scope it was created. potentially generated by the
* service.
*/
@Override
public String getProviderId();
/**
* user defined name of the server.
*
* @return user defined name of the server.
*/
@Override
@Nullable
public String getName();
/**
@ -56,7 +59,12 @@ public interface ComputeMetadata extends ResourceMetadata<ComputeType> {
* a node or image is region based, the id will likely include both the region and the
* provider-supplied id encoded to avoid collisions.
*
* @return unique id within your account on the provider
*/
public String getId();
/**
* @return tags describing this resource, if supported
*/
public Set<String> getTags();
}

View File

@ -22,11 +22,14 @@ import static com.google.common.base.Preconditions.checkNotNull;
import java.net.URI;
import java.util.Map;
import java.util.Set;
import org.jclouds.compute.domain.internal.ComputeMetadataImpl;
import org.jclouds.domain.Location;
import org.jclouds.domain.ResourceMetadataBuilder;
import com.google.common.collect.ImmutableSet;
/**
*
* @author Adrian Cole
@ -34,9 +37,9 @@ import org.jclouds.domain.ResourceMetadataBuilder;
public class ComputeMetadataBuilder extends ResourceMetadataBuilder<ComputeType> {
protected String id;
protected ComputeType type;
protected Set<String> tags = ImmutableSet.<String>of();
public ComputeMetadataBuilder(ComputeType type) {
super();
this.type = checkNotNull(type, "type");
}
@ -45,6 +48,11 @@ public class ComputeMetadataBuilder extends ResourceMetadataBuilder<ComputeType>
return this;
}
public ComputeMetadataBuilder tags(Set<String> tags) {
this.tags = ImmutableSet.<String> copyOf(checkNotNull(tags, "tags"));
return this;
}
/**
* set id and providerId to the same value;
*/
@ -79,11 +87,11 @@ public class ComputeMetadataBuilder extends ResourceMetadataBuilder<ComputeType>
}
public ComputeMetadata build() {
return new ComputeMetadataImpl(type, providerId, name, id, location, uri, userMetadata);
return new ComputeMetadataImpl(type, providerId, name, id, location, uri, userMetadata, tags);
}
public static ComputeMetadataBuilder fromComputeMetadata(ComputeMetadata in) {
return new ComputeMetadataBuilder(in.getType()).id(in.getId()).location(in.getLocation()).name(in.getName())
.uri(in.getUri()).userMetadata(in.getUserMetadata());
.uri(in.getUri()).userMetadata(in.getUserMetadata()).tags(in.getTags());
}
}

View File

@ -25,6 +25,7 @@ import static org.jclouds.compute.predicates.ImagePredicates.any;
import java.net.URI;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.jclouds.compute.domain.internal.HardwareImpl;
import org.jclouds.compute.predicates.ImagePredicates;
@ -88,6 +89,11 @@ public class HardwareBuilder extends ComputeMetadataBuilder {
return HardwareBuilder.class.cast(super.id(id));
}
@Override
public HardwareBuilder tags(Set<String> tags) {
return HardwareBuilder.class.cast(super.tags(tags));
}
@Override
public HardwareBuilder ids(String id) {
return HardwareBuilder.class.cast(super.ids(id));
@ -120,14 +126,14 @@ public class HardwareBuilder extends ComputeMetadataBuilder {
@Override
public Hardware build() {
return new HardwareImpl(providerId, name, id, location, uri, userMetadata, processors, ram, volumes,
return new HardwareImpl(providerId, name, id, location, uri, userMetadata, tags, processors, ram, volumes,
supportsImage);
}
@SuppressWarnings("unchecked")
public static HardwareBuilder fromHardware(Hardware in) {
return new HardwareBuilder().id(in.getId()).providerId(in.getProviderId()).location(in.getLocation()).name(
in.getName()).uri(in.getUri()).userMetadata(in.getUserMetadata()).processors(
in.getName()).uri(in.getUri()).userMetadata(in.getUserMetadata()).tags(in.getTags()).processors(
List.class.cast(in.getProcessors())).ram(in.getRam()).volumes(List.class.cast(in.getVolumes()))
.supportsImage(in.supportsImage());
}

View File

@ -22,6 +22,7 @@ import static com.google.common.base.Preconditions.checkNotNull;
import java.net.URI;
import java.util.Map;
import java.util.Set;
import javax.annotation.Nullable;
@ -74,6 +75,10 @@ public class ImageBuilder extends ComputeMetadataBuilder {
return ImageBuilder.class.cast(super.id(id));
}
public ImageBuilder tags(Set<String> tags) {
return ImageBuilder.class.cast(super.tags(tags));
}
@Override
public ImageBuilder ids(String id) {
return ImageBuilder.class.cast(super.ids(id));
@ -106,13 +111,13 @@ public class ImageBuilder extends ComputeMetadataBuilder {
@Override
public Image build() {
return new ImageImpl(providerId, name, id, location, uri, userMetadata, operatingSystem, description, version,
return new ImageImpl(providerId, name, id, location, uri, userMetadata, tags, operatingSystem, description, version,
adminPassword, defaultCredentials);
}
public static ImageBuilder fromImage(Image image) {
return new ImageBuilder().providerId(image.getProviderId()).name(image.getName()).id(image.getId()).location(
image.getLocation()).uri(image.getUri()).userMetadata(image.getUserMetadata()).version(
image.getLocation()).uri(image.getUri()).userMetadata(image.getUserMetadata()).tags(image.getTags()).version(
image.getVersion()).description(image.getDescription()).operatingSystem(image.getOperatingSystem())
.adminPassword(image.getAdminPassword()).defaultCredentials(image.getDefaultCredentials());
}

View File

@ -113,6 +113,11 @@ public class NodeMetadataBuilder extends ComputeMetadataBuilder {
return NodeMetadataBuilder.class.cast(super.id(id));
}
@Override
public NodeMetadataBuilder tags(Set<String> tags) {
return NodeMetadataBuilder.class.cast(super.tags(tags));
}
@Override
public NodeMetadataBuilder ids(String id) {
return NodeMetadataBuilder.class.cast(super.ids(id));
@ -145,17 +150,17 @@ public class NodeMetadataBuilder extends ComputeMetadataBuilder {
@Override
public NodeMetadata build() {
return new NodeMetadataImpl(providerId, name, id, location, uri, userMetadata, group, hardware, imageId, os, state,
loginPort, publicAddresses, privateAddresses, adminPassword, credentials);
return new NodeMetadataImpl(providerId, name, id, location, uri, userMetadata, tags, group, hardware, imageId,
os, state, loginPort, publicAddresses, privateAddresses, adminPassword, credentials);
}
public static NodeMetadataBuilder fromNodeMetadata(NodeMetadata node) {
return new NodeMetadataBuilder().providerId(node.getProviderId()).name(node.getName()).id(node.getId()).location(
node.getLocation()).uri(node.getUri()).userMetadata(node.getUserMetadata()).group(node.getGroup()).hardware(
node.getHardware()).imageId(node.getImageId()).operatingSystem(node.getOperatingSystem()).state(
node.getState()).loginPort(node.getLoginPort()).publicAddresses(node.getPublicAddresses())
.privateAddresses(node.getPrivateAddresses()).adminPassword(node.getAdminPassword()).credentials(
node.getCredentials());
node.getLocation()).uri(node.getUri()).userMetadata(node.getUserMetadata()).tags(node.getTags()).group(
node.getGroup()).hardware(node.getHardware()).imageId(node.getImageId()).operatingSystem(
node.getOperatingSystem()).state(node.getState()).loginPort(node.getLoginPort()).publicAddresses(
node.getPublicAddresses()).privateAddresses(node.getPrivateAddresses()).adminPassword(
node.getAdminPassword()).credentials(node.getCredentials());
}
}

View File

@ -42,7 +42,7 @@ public class OsFamilyVersion64Bit {
@Override
public String toString() {
return "OsFamilyVersion64Bit [family=" + family + ", version=" + version + ", is64Bit=" + is64Bit + "]";
return "[family=" + family + ", version=" + version + ", is64Bit=" + is64Bit + "]";
}
@Override

View File

@ -22,12 +22,15 @@ import static com.google.common.base.Preconditions.checkNotNull;
import java.net.URI;
import java.util.Map;
import java.util.Set;
import org.jclouds.compute.domain.ComputeMetadata;
import org.jclouds.compute.domain.ComputeType;
import org.jclouds.domain.Location;
import org.jclouds.domain.internal.ResourceMetadataImpl;
import com.google.common.collect.ImmutableSet;
/**
* @author Adrian Cole
* @author Ivan Meredith
@ -37,12 +40,14 @@ public class ComputeMetadataImpl extends ResourceMetadataImpl<ComputeType> imple
private static final long serialVersionUID = 7374704415964898694L;
private final String id;
private final ComputeType type;
protected final Set<String> tags;
public ComputeMetadataImpl(ComputeType type, String providerId, String name, String id, Location location, URI uri,
Map<String, String> userMetadata) {
Map<String, String> userMetadata, Set<String> tags) {
super(providerId, name, location, uri, userMetadata);
this.id = checkNotNull(id, "id");
this.type = checkNotNull(type, "type");
this.tags = ImmutableSet.<String> copyOf(checkNotNull(tags, "tags"));
}
/**
@ -61,6 +66,14 @@ public class ComputeMetadataImpl extends ResourceMetadataImpl<ComputeType> imple
return id;
}
/**
* {@inheritDoc}
*/
@Override
public Set<String> getTags() {
return tags;
}
@Override
public int hashCode() {
final int prime = 31;

View File

@ -25,6 +25,7 @@ import static org.jclouds.compute.util.ComputeServiceUtils.getSpace;
import java.net.URI;
import java.util.List;
import java.util.Map;
import java.util.Set;
import javax.annotation.Nullable;
@ -53,9 +54,9 @@ public class HardwareImpl extends ComputeMetadataImpl implements Hardware {
private final Predicate<Image> supportsImage;
public HardwareImpl(String providerId, String name, String id, @Nullable Location location, URI uri,
Map<String, String> userMetadata, Iterable<? extends Processor> processors, int ram,
Map<String, String> userMetadata, Set<String> tags, Iterable<? extends Processor> processors, int ram,
Iterable<? extends Volume> volumes, Predicate<Image> supportsImage) {
super(ComputeType.HARDWARE, providerId, name, id, location, uri, userMetadata);
super(ComputeType.HARDWARE, providerId, name, id, location, uri, userMetadata, tags);
this.processors = ImmutableList.copyOf(checkNotNull(processors, "processors"));
this.ram = ram;
this.volumes = ImmutableList.copyOf(checkNotNull(volumes, "volumes"));
@ -106,7 +107,7 @@ public class HardwareImpl extends ComputeMetadataImpl implements Hardware {
@Override
public String toString() {
return "[id=" + getId() + ", providerId=" + getProviderId() + ", name=" + getName() + ", processors="
+ processors + ", ram=" + ram + ", volumes=" + volumes + ", supportsImage=" + supportsImage + "]";
+ processors + ", ram=" + ram + ", volumes=" + volumes + ", supportsImage=" + supportsImage + ", tags=" + tags + "]";
}
/**

View File

@ -22,6 +22,7 @@ import static com.google.common.base.Preconditions.checkNotNull;
import java.net.URI;
import java.util.Map;
import java.util.Set;
import javax.annotation.Nullable;
@ -47,9 +48,9 @@ public class ImageImpl extends ComputeMetadataImpl implements Image {
private final Credentials defaultCredentials;
public ImageImpl(String providerId, String name, String id, Location location, URI uri,
Map<String, String> userMetadata, OperatingSystem operatingSystem, String description,
Map<String, String> userMetadata, Set<String> tags, OperatingSystem operatingSystem, String description,
@Nullable String version, @Nullable String adminPassword, @Nullable Credentials defaultCredentials) {
super(ComputeType.IMAGE, providerId, name, id, location, uri, userMetadata);
super(ComputeType.IMAGE, providerId, name, id, location, uri, userMetadata, tags);
this.operatingSystem = checkNotNull(operatingSystem, "operatingSystem");
this.version = version;
this.description = checkNotNull(description, "description");
@ -102,7 +103,7 @@ public class ImageImpl extends ComputeMetadataImpl implements Image {
return "[id=" + getId() + ", name=" + getName() + ", operatingSystem=" + operatingSystem + ", description="
+ description + ", version=" + version + ", location=" + getLocation() + ", loginUser="
+ ((defaultCredentials != null) ? defaultCredentials.identity : null) + ", userMetadata="
+ getUserMetadata() + "]";
+ getUserMetadata() + ", tags=" + tags + "]";
}
@Override

View File

@ -63,11 +63,11 @@ public class NodeMetadataImpl extends ComputeMetadataImpl implements NodeMetadat
private final OperatingSystem os;
public NodeMetadataImpl(String providerId, String name, String id, Location location, URI uri,
Map<String, String> userMetadata, @Nullable String group, @Nullable Hardware hardware,
Map<String, String> userMetadata, Set<String> tags, @Nullable String group, @Nullable Hardware hardware,
@Nullable String imageId, @Nullable OperatingSystem os, NodeState state, int loginPort,
Iterable<String> publicAddresses, Iterable<String> privateAddresses, @Nullable String adminPassword,
@Nullable Credentials credentials) {
super(ComputeType.NODE, providerId, name, id, location, uri, userMetadata);
super(ComputeType.NODE, providerId, name, id, location, uri, userMetadata, tags);
this.group = group;
this.hardware = hardware;
this.imageId = imageId;
@ -175,7 +175,7 @@ public class NodeMetadataImpl extends ComputeMetadataImpl implements NodeMetadat
+ getOperatingSystem() + ", state=" + getState() + ", loginPort=" + getLoginPort()
+ ", privateAddresses=" + privateAddresses + ", publicAddresses=" + publicAddresses + ", hardware="
+ getHardware() + ", loginUser=" + ((credentials != null) ? credentials.identity : null)
+ ", userMetadata=" + getUserMetadata() + "]";
+ ", userMetadata=" + getUserMetadata() + ", tags=" + tags + "]";
}
@Override

View File

@ -557,10 +557,10 @@ public class TemplateBuilderImpl implements TemplateBuilder {
}
protected Hardware resolveSize(Ordering<Hardware> hardwareOrdering, final Iterable<? extends Image> images) {
Set<? extends Hardware> hardwaresl = hardwares.get();
Set<? extends Hardware> hardwarel = hardwares.get();
Hardware hardware;
try {
Iterable<? extends Hardware> hardwaresThatAreCompatibleWithOurImages = filter(hardwaresl,
Iterable<? extends Hardware> hardwaresThatAreCompatibleWithOurImages = filter(hardwarel,
new Predicate<Hardware>() {
@Override
public boolean apply(final Hardware hardware) {
@ -582,7 +582,7 @@ public class TemplateBuilderImpl implements TemplateBuilder {
});
hardware = hardwareOrdering.max(filter(hardwaresThatAreCompatibleWithOurImages, hardwarePredicate));
} catch (NoSuchElementException exception) {
throw new NoSuchElementException("hardwares don't support any images: " + toString() + "\n" + hardwaresl
throw new NoSuchElementException("hardware don't support any images: " + toString() + "\n" + hardwarel
+ "\n" + images);
}
logger.debug("<< matched hardware(%s)", hardware);

View File

@ -62,6 +62,7 @@ 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.NodeState;
import org.jclouds.compute.domain.Template;
import org.jclouds.compute.domain.TemplateBuilder;
import org.jclouds.compute.options.RunScriptOptions;
@ -78,8 +79,8 @@ import org.jclouds.compute.strategy.ResumeNodeStrategy;
import org.jclouds.compute.strategy.RunScriptOnNodeAndAddToGoodMapOrPutExceptionIntoBadMap;
import org.jclouds.compute.strategy.SuspendNodeStrategy;
import org.jclouds.domain.Credentials;
import org.jclouds.domain.Credentials.Builder;
import org.jclouds.domain.Location;
import org.jclouds.domain.Credentials.Builder;
import org.jclouds.io.Payload;
import org.jclouds.logging.Logger;
import org.jclouds.predicates.RetryablePredicate;
@ -132,22 +133,25 @@ public class BaseComputeService implements ComputeService {
private final Timeouts timeouts;
private final InitAdminAccess initAdminAccess;
private final PersistNodeCredentials persistNodeCredentials;
private final RunScriptOnNode.Factory runScriptOnNodeFactory;
private final ExecutorService executor;
@Inject
protected BaseComputeService(ComputeServiceContext context, Map<String, Credentials> credentialStore,
@Memoized Supplier<Set<? extends Image>> images, @Memoized Supplier<Set<? extends Hardware>> hardwareProfiles,
@Memoized Supplier<Set<? extends Location>> locations, ListNodesStrategy listNodesStrategy,
GetNodeMetadataStrategy getNodeMetadataStrategy, CreateNodesInGroupThenAddToSet runNodesAndAddToSetStrategy,
RebootNodeStrategy rebootNodeStrategy, DestroyNodeStrategy destroyNodeStrategy,
ResumeNodeStrategy resumeNodeStrategy, SuspendNodeStrategy suspendNodeStrategy,
Provider<TemplateBuilder> templateBuilderProvider, Provider<TemplateOptions> templateOptionsProvider,
@Named("NODE_RUNNING") Predicate<NodeMetadata> nodeRunning,
@Named("NODE_TERMINATED") Predicate<NodeMetadata> nodeTerminated,
@Named("NODE_SUSPENDED") Predicate<NodeMetadata> nodeSuspended,
InitializeRunScriptOnNodeOrPlaceInBadMap.Factory initScriptRunnerFactory, InitAdminAccess initAdminAccess,
PersistNodeCredentials persistNodeCredentials, Timeouts timeouts,
@Named(Constants.PROPERTY_USER_THREADS) ExecutorService executor) {
@Memoized Supplier<Set<? extends Image>> images,
@Memoized Supplier<Set<? extends Hardware>> hardwareProfiles,
@Memoized Supplier<Set<? extends Location>> locations, ListNodesStrategy listNodesStrategy,
GetNodeMetadataStrategy getNodeMetadataStrategy,
CreateNodesInGroupThenAddToSet runNodesAndAddToSetStrategy, RebootNodeStrategy rebootNodeStrategy,
DestroyNodeStrategy destroyNodeStrategy, ResumeNodeStrategy resumeNodeStrategy,
SuspendNodeStrategy suspendNodeStrategy, Provider<TemplateBuilder> templateBuilderProvider,
Provider<TemplateOptions> templateOptionsProvider,
@Named("NODE_RUNNING") Predicate<NodeMetadata> nodeRunning,
@Named("NODE_TERMINATED") Predicate<NodeMetadata> nodeTerminated,
@Named("NODE_SUSPENDED") Predicate<NodeMetadata> nodeSuspended,
InitializeRunScriptOnNodeOrPlaceInBadMap.Factory initScriptRunnerFactory, InitAdminAccess initAdminAccess,
RunScriptOnNode.Factory runScriptOnNodeFactory, PersistNodeCredentials persistNodeCredentials,
Timeouts timeouts, @Named(Constants.PROPERTY_USER_THREADS) ExecutorService executor) {
this.context = checkNotNull(context, "context");
this.credentialStore = checkNotNull(credentialStore, "credentialStore");
this.images = checkNotNull(images, "images");
@ -168,6 +172,7 @@ public class BaseComputeService implements ComputeService {
this.initScriptRunnerFactory = checkNotNull(initScriptRunnerFactory, "initScriptRunnerFactory");
this.timeouts = checkNotNull(timeouts, "timeouts");
this.initAdminAccess = checkNotNull(initAdminAccess, "initAdminAccess");
this.runScriptOnNodeFactory = checkNotNull(runScriptOnNodeFactory, "runScriptOnNodeFactory");
this.persistNodeCredentials = checkNotNull(persistNodeCredentials, "persistNodeCredentials");
this.executor = checkNotNull(executor, "executor");
}
@ -185,7 +190,7 @@ public class BaseComputeService implements ComputeService {
*/
@Override
public Set<? extends NodeMetadata> runNodesWithTag(String group, int count, Template template)
throws RunNodesException {
throws RunNodesException {
return createNodesInGroup(group, count, template);
}
@ -194,7 +199,7 @@ public class BaseComputeService implements ComputeService {
*/
@Override
public Set<? extends NodeMetadata> runNodesWithTag(String group, int count, TemplateOptions templateOptions)
throws RunNodesException {
throws RunNodesException {
return createNodesInGroup(group, count, templateBuilder().any().options(templateOptions).build());
}
@ -208,12 +213,12 @@ public class BaseComputeService implements ComputeService {
@Override
public Set<? extends NodeMetadata> createNodesInGroup(String group, int count, Template template)
throws RunNodesException {
throws RunNodesException {
checkNotNull(group, "group cannot be null");
checkNotNull(template.getLocation(), "location");
logger.debug(">> running %d node%s group(%s) location(%s) image(%s) hardwareProfile(%s) options(%s)", count,
count > 1 ? "s" : "", group, template.getLocation().getId(), template.getImage().getId(), template
.getHardware().getId(), template.getOptions());
count > 1 ? "s" : "", group, template.getLocation().getId(), template.getImage().getId(), template
.getHardware().getId(), template.getOptions());
Set<NodeMetadata> goodNodes = newLinkedHashSet();
Map<NodeMetadata, Exception> badNodes = newLinkedHashMap();
Multimap<NodeMetadata, CustomizationResponse> customizationResponses = LinkedHashMultimap.create();
@ -222,9 +227,9 @@ public class BaseComputeService implements ComputeService {
template.getOptions().runScript(initAdminAccess.apply(template.getOptions().getRunScript()));
Map<?, Future<Void>> responses = runNodesAndAddToSetStrategy.execute(group, count, template, goodNodes, badNodes,
customizationResponses);
customizationResponses);
Map<?, Exception> executionExceptions = awaitCompletion(responses, executor, null, logger, "runNodesWithTag("
+ group + ")");
+ group + ")");
Function<NodeMetadata, NodeMetadata> fn = persistNodeCredentials.always(template.getOptions().getRunScript());
badNodes = Maps2.transformKeys(badNodes, fn);
goodNodes = ImmutableSet.copyOf(Iterables.transform(goodNodes, fn));
@ -236,7 +241,7 @@ public class BaseComputeService implements ComputeService {
@Override
public Set<? extends NodeMetadata> createNodesInGroup(String group, int count, TemplateOptions templateOptions)
throws RunNodesException {
throws RunNodesException {
return createNodesInGroup(group, count, templateBuilder().any().options(templateOptions).build());
}
@ -282,27 +287,27 @@ public class BaseComputeService implements ComputeService {
public Set<? extends NodeMetadata> destroyNodesMatching(Predicate<NodeMetadata> filter) {
logger.debug(">> destroying nodes matching(%s)", filter);
Set<NodeMetadata> set = newLinkedHashSet(transformParallel(nodesMatchingFilterAndNotTerminated(filter),
new Function<NodeMetadata, Future<NodeMetadata>>() {
new Function<NodeMetadata, Future<NodeMetadata>>() {
// TODO make an async interface instead of re-wrapping
@Override
public Future<NodeMetadata> apply(final NodeMetadata from) {
return executor.submit(new Callable<NodeMetadata>() {
// TODO make an async interface instead of re-wrapping
@Override
public Future<NodeMetadata> apply(final NodeMetadata from) {
return executor.submit(new Callable<NodeMetadata>() {
@Override
public NodeMetadata call() throws Exception {
destroyNode(from.getId());
return from;
}
@Override
public NodeMetadata call() throws Exception {
destroyNode(from.getId());
return from;
}
@Override
public String toString() {
return "destroyNode(" + from.getId() + ")";
}
});
}
@Override
public String toString() {
return "destroyNode(" + from.getId() + ")";
}
});
}
}, executor, null, logger, "destroyNodesMatching(" + filter + ")"));
}, executor, null, logger, "destroyNodesMatching(" + filter + ")"));
logger.debug("<< destroyed(%d)", set.size());
return set;
}
@ -316,7 +321,7 @@ public class BaseComputeService implements ComputeService {
* if none found
*/
Iterable<? extends NodeMetadata> nodesMatchingFilterAndNotTerminatedExceptionIfNotFound(
Predicate<NodeMetadata> filter) {
Predicate<NodeMetadata> filter) {
Iterable<? extends NodeMetadata> nodes = nodesMatchingFilterAndNotTerminated(filter);
if (Iterables.size(nodes) == 0)
throw new NoSuchElementException("no nodes matched filter: " + filter);
@ -406,15 +411,15 @@ public class BaseComputeService implements ComputeService {
public void rebootNodesMatching(Predicate<NodeMetadata> filter) {
logger.debug(">> rebooting nodes matching(%s)", filter);
transformParallel(nodesMatchingFilterAndNotTerminatedExceptionIfNotFound(filter),
new Function<NodeMetadata, Future<Void>>() {
// TODO use native async
@Override
public Future<Void> apply(NodeMetadata from) {
rebootNode(from.getId());
return immediateFuture(null);
}
new Function<NodeMetadata, Future<Void>>() {
// TODO use native async
@Override
public Future<Void> apply(NodeMetadata from) {
rebootNode(from.getId());
return immediateFuture(null);
}
}, executor, null, logger, "rebootNodesMatching(" + filter + ")");
}, executor, null, logger, "rebootNodesMatching(" + filter + ")");
logger.debug("<< rebooted");
}
@ -437,15 +442,15 @@ public class BaseComputeService implements ComputeService {
public void resumeNodesMatching(Predicate<NodeMetadata> filter) {
logger.debug(">> resuming nodes matching(%s)", filter);
transformParallel(nodesMatchingFilterAndNotTerminatedExceptionIfNotFound(filter),
new Function<NodeMetadata, Future<Void>>() {
// TODO use native async
@Override
public Future<Void> apply(NodeMetadata from) {
resumeNode(from.getId());
return immediateFuture(null);
}
new Function<NodeMetadata, Future<Void>>() {
// TODO use native async
@Override
public Future<Void> apply(NodeMetadata from) {
resumeNode(from.getId());
return immediateFuture(null);
}
}, executor, null, logger, "resumeNodesMatching(" + filter + ")");
}, executor, null, logger, "resumeNodesMatching(" + filter + ")");
logger.debug("<< resumed");
}
@ -468,15 +473,15 @@ public class BaseComputeService implements ComputeService {
public void suspendNodesMatching(Predicate<NodeMetadata> filter) {
logger.debug(">> suspending nodes matching(%s)", filter);
transformParallel(nodesMatchingFilterAndNotTerminatedExceptionIfNotFound(filter),
new Function<NodeMetadata, Future<Void>>() {
// TODO use native async
@Override
public Future<Void> apply(NodeMetadata from) {
suspendNode(from.getId());
return immediateFuture(null);
}
new Function<NodeMetadata, Future<Void>>() {
// TODO use native async
@Override
public Future<Void> apply(NodeMetadata from) {
suspendNode(from.getId());
return immediateFuture(null);
}
}, executor, null, logger, "suspendNodesMatching(" + filter + ")");
}, executor, null, logger, "suspendNodesMatching(" + filter + ")");
logger.debug("<< suspended");
}
@ -485,7 +490,7 @@ public class BaseComputeService implements ComputeService {
*/
@Override
public Map<NodeMetadata, ExecResponse> runScriptOnNodesMatching(Predicate<NodeMetadata> filter, Payload runScript)
throws RunScriptOnNodesException {
throws RunScriptOnNodesException {
return runScriptOnNodesMatching(filter, runScript, RunScriptOptions.NONE);
}
@ -494,10 +499,10 @@ public class BaseComputeService implements ComputeService {
*/
@Override
public Map<NodeMetadata, ExecResponse> runScriptOnNodesMatching(Predicate<NodeMetadata> filter, Payload runScript,
RunScriptOptions options) throws RunScriptOnNodesException {
RunScriptOptions options) throws RunScriptOnNodesException {
try {
return runScriptOnNodesMatching(filter,
Statements.exec(Strings2.toStringAndClose(checkNotNull(runScript, "runScript").getInput())), options);
return runScriptOnNodesMatching(filter, Statements.exec(Strings2.toStringAndClose(checkNotNull(runScript,
"runScript").getInput())), options);
} catch (IOException e) {
Throwables.propagate(e);
return null;
@ -509,7 +514,7 @@ public class BaseComputeService implements ComputeService {
*/
@Override
public Map<NodeMetadata, ExecResponse> runScriptOnNodesMatching(Predicate<NodeMetadata> filter, String runScript)
throws RunScriptOnNodesException {
throws RunScriptOnNodesException {
return runScriptOnNodesMatching(filter, Statements.exec(checkNotNull(runScript, "runScript")));
}
@ -518,15 +523,15 @@ public class BaseComputeService implements ComputeService {
*/
@Override
public Map<NodeMetadata, ExecResponse> runScriptOnNodesMatching(Predicate<NodeMetadata> filter, Statement runScript)
throws RunScriptOnNodesException {
throws RunScriptOnNodesException {
return runScriptOnNodesMatching(filter, runScript, RunScriptOptions.NONE);
}
@Override
public Map<? extends NodeMetadata, ExecResponse> runScriptOnNodesMatching(Predicate<NodeMetadata> filter,
String runScript, RunScriptOptions options) throws RunScriptOnNodesException {
String runScript, RunScriptOptions options) throws RunScriptOnNodesException {
return runScriptOnNodesMatching(filter, Statements.exec(checkNotNull(runScript, "runScript")),
RunScriptOptions.NONE);
RunScriptOptions.NONE);
}
/**
@ -534,7 +539,7 @@ public class BaseComputeService implements ComputeService {
*/
@Override
public Map<NodeMetadata, ExecResponse> runScriptOnNodesMatching(Predicate<NodeMetadata> filter, Statement runScript,
RunScriptOptions options) throws RunScriptOnNodesException {
RunScriptOptions options) throws RunScriptOnNodesException {
checkNotNull(filter, "filter");
checkNotNull(runScript, "runScript");
@ -548,11 +553,11 @@ public class BaseComputeService implements ComputeService {
runScript = initAdminAccess.apply(runScript);
Iterable<? extends RunScriptOnNode> scriptRunners = transformNodesIntoInitializedScriptRunners(
nodesMatchingFilterAndNotTerminatedExceptionIfNotFound(filter), runScript, options, badNodes);
nodesMatchingFilterAndNotTerminatedExceptionIfNotFound(filter), runScript, options, badNodes);
if (Iterables.size(scriptRunners) > 0) {
for (RunScriptOnNode runner : scriptRunners) {
responses.put(runner.getNode(), executor.submit(new RunScriptOnNodeAndAddToGoodMapOrPutExceptionIntoBadMap(
runner, goodNodes, badNodes)));
runner, goodNodes, badNodes)));
}
exceptions = awaitCompletion(responses, executor, null, logger, "runScriptOnNodesMatching(" + filter + ")");
}
@ -567,12 +572,49 @@ public class BaseComputeService implements ComputeService {
return goodNodes;
}
/**
* {@inheritDoc}
*/
@Override
public ExecResponse runScriptOnNode(String id, String runScript) {
return runScriptOnNode(id, runScript, RunScriptOptions.NONE);
}
/**
* {@inheritDoc}
*/
@Override
public ExecResponse runScriptOnNode(String id, String runScript, RunScriptOptions options) {
return runScriptOnNode(id, Statements.exec(checkNotNull(runScript, "runScript")), options);
}
/**
* {@inheritDoc}
*/
@Override
public ExecResponse runScriptOnNode(String id, Statement runScript) {
return runScriptOnNode(id, runScript, RunScriptOptions.NONE);
}
/**
* {@inheritDoc}
*/
@Override
public ExecResponse runScriptOnNode(String id, Statement runScript, RunScriptOptions options) {
NodeMetadata node = this.getNodeMetadata(id);
if (node == null)
throw new NoSuchElementException(id);
if (node.getState() != NodeState.RUNNING)
throw new IllegalStateException("node " + id
+ " needs to be running before executing a script on it. current state: " + node.getState());
return runScriptOnNodeFactory.create(node, runScript, options).init().call();
}
private Iterable<? extends RunScriptOnNode> transformNodesIntoInitializedScriptRunners(
Iterable<? extends NodeMetadata> nodes, Statement script, RunScriptOptions options,
Map<NodeMetadata, Exception> badNodes) {
return filter(
transformParallel(nodes, new TransformNodesIntoInitializedScriptRunners(script, options, badNodes),
executor, null, logger, "initialize script runners"), notNull());
Iterable<? extends NodeMetadata> nodes, Statement script, RunScriptOptions options,
Map<NodeMetadata, Exception> badNodes) {
return filter(transformParallel(nodes, new TransformNodesIntoInitializedScriptRunners(script, options, badNodes),
executor, null, logger, "initialize script runners"), notNull());
}
private Set<? extends NodeMetadata> detailsOnAllNodes() {
@ -585,13 +627,13 @@ public class BaseComputeService implements ComputeService {
}
private final class TransformNodesIntoInitializedScriptRunners implements
Function<NodeMetadata, Future<RunScriptOnNode>> {
Function<NodeMetadata, Future<RunScriptOnNode>> {
private final Map<NodeMetadata, Exception> badNodes;
private final Statement script;
private final RunScriptOptions options;
private TransformNodesIntoInitializedScriptRunners(Statement script, RunScriptOptions options,
Map<NodeMetadata, Exception> badNodes) {
Map<NodeMetadata, Exception> badNodes) {
this.badNodes = checkNotNull(badNodes, "badNodes");
this.script = checkNotNull(script, "script");
this.options = checkNotNull(options, "options");
@ -602,7 +644,7 @@ public class BaseComputeService implements ComputeService {
checkNotNull(node, "node");
if (options.getOverridingCredentials() != null) {
Builder<? extends Credentials> builder = node.getCredentials() != null ? node.getCredentials().toBuilder()
: new Credentials.Builder<Credentials>();
: new Credentials.Builder<Credentials>();
if (options.getOverridingCredentials().identity != null)
builder.identity(options.getOverridingCredentials().identity);
if (options.getOverridingCredentials().credential != null)

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.Set;
import org.jclouds.domain.Credentials;
import org.jclouds.io.Payload;
@ -31,6 +32,7 @@ import org.jclouds.scriptbuilder.domain.Statements;
import org.jclouds.util.Strings2;
import com.google.common.base.Throwables;
import com.google.common.collect.ImmutableSet;
/**
* Contains options supported in the {@code ComputeService#runNodesWithTag} operation. <h2>
@ -70,6 +72,8 @@ public class TemplateOptions extends RunScriptOptions implements Cloneable {
to.blockOnPort(this.getPort(), this.getSeconds());
if (this.isIncludeMetadata())
to.withMetadata();
if (this.getTags().size() > 0)
to.tags(getTags());
if (!this.shouldBlockUntilRunning())
to.blockUntilRunning(false);
if (!this.shouldBlockOnComplete())
@ -276,6 +280,8 @@ public class TemplateOptions extends RunScriptOptions implements Cloneable {
protected Statement script;
protected Set<String> tags = ImmutableSet.of();
protected String privateKey;
protected String publicKey;
@ -292,6 +298,10 @@ public class TemplateOptions extends RunScriptOptions implements Cloneable {
return script;
}
public Set<String> getTags() {
return tags;
}
public String getPrivateKey() {
return privateKey;
}
@ -350,7 +360,7 @@ public class TemplateOptions extends RunScriptOptions implements Cloneable {
*/
public TemplateOptions installPrivateKey(String privateKey) {
checkArgument(checkNotNull(privateKey, "privateKey").startsWith("-----BEGIN RSA PRIVATE KEY-----"),
"key should start with -----BEGIN RSA PRIVATE KEY-----");
"key should start with -----BEGIN RSA PRIVATE KEY-----");
this.privateKey = privateKey;
return this;
}
@ -403,6 +413,14 @@ public class TemplateOptions extends RunScriptOptions implements Cloneable {
}
}
/**
* assigns tags to the created nodes
*/
public TemplateOptions tags(Iterable<String> tags) {
this.tags = ImmutableSet.copyOf(checkNotNull(tags, "tags"));
return this;
}
/**
* Opens the set of ports to public access.
*/
@ -461,6 +479,14 @@ public class TemplateOptions extends RunScriptOptions implements Cloneable {
return options.inboundPorts(ports);
}
/**
* @see TemplateOptions#tags
*/
public static TemplateOptions tags(Iterable<String> tags) {
TemplateOptions options = new TemplateOptions();
return options.tags(tags);
}
/**
* @see TemplateOptions#blockUntilRunning
*/
@ -556,9 +582,9 @@ public class TemplateOptions extends RunScriptOptions implements Cloneable {
@Override
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 + "]";
+ (publicKey != null) + ", runScript=" + (script != null) + ", blockUntilRunning=" + blockUntilRunning
+ ", blockOnComplete=" + blockOnComplete + ", port:seconds=" + port + ":" + seconds
+ ", metadata/details: " + includeMetadata + "]";
}
public TemplateOptions blockUntilRunning(boolean blockUntilRunning) {

View File

@ -57,7 +57,7 @@ public interface ComputeServiceConstants {
public static class ReferenceData {
@Inject(optional = true)
@Named(PROPERTY_OS_VERSION_MAP_JSON)
public String osVersionMapJson = "{\"centos\":{\"\":\"\",\"5\":\"5.0\",\"5.2\":\"5.2\",\"5.3\":\"5.3\",\"5.4\":\"5.4\",\"5.5\":\"5.5\"},\"rhel\":{\"\":\"\",\"5\":\"5.0\",\"5.2\":\"5.2\",\"5.3\":\"5.3\",\"5.4\":\"5.4\",\"5.5\":\"5.5\"},\"solaris\":{\"\":\"\",\"10\":\"10\"},\"ubuntu\":{\"\":\"\",\"hardy\":\"8.04\",\"karmic\":\"9.10\",\"lucid\":\"10.04\",\"maverick\":\"10.10\",\"natty\":\"11.04\"},\"windows\":{\"\":\"\",\"2003\":\"2003\",\"2003 Standard\":\"2003\",\"2003 R2\":\"2003 R2\",\"2008\":\"2008\",\"2008 Web\":\"2008\",\"2008 Server\":\"2008\",\"Server 2008\":\"2008\",\"2008 R2\":\"2008 R2\",\"Server 2008 R2\":\"2008 R2\",\"2008 Server R2\":\"2008 R2\",\"2008 SP2\":\"2008 SP2\",\"Server 2008 SP2\":\"2008 SP2\"}}";
public String osVersionMapJson = "{\"suse\":{\"\":\"\",\"11\":\"11\",\"11 SP1\":\"11 SP1\"},\"centos\":{\"\":\"\",\"5\":\"5.0\",\"5.2\":\"5.2\",\"5.3\":\"5.3\",\"5.4\":\"5.4\",\"5.5\":\"5.5\"},\"rhel\":{\"\":\"\",\"5\":\"5.0\",\"5.2\":\"5.2\",\"5.3\":\"5.3\",\"5.4\":\"5.4\",\"5.5\":\"5.5\"},\"solaris\":{\"\":\"\",\"10\":\"10\"},\"ubuntu\":{\"\":\"\",\"hardy\":\"8.04\",\"karmic\":\"9.10\",\"lucid\":\"10.04\",\"maverick\":\"10.10\",\"natty\":\"11.04\"},\"windows\":{\"\":\"\",\"2003\":\"2003\",\"2003 Standard\":\"2003\",\"2003 R2\":\"2003 R2\",\"2008\":\"2008\",\"2008 Web\":\"2008\",\"2008 Server\":\"2008\",\"Server 2008\":\"2008\",\"2008 R1\":\"2008 R1\",\"2008 R2\":\"2008 R2\",\"Server 2008 R2\":\"2008 R2\",\"2008 Server R2\":\"2008 R2\",\"2008 SP2\":\"2008 SP2\",\"Server 2008 SP2\":\"2008 SP2\"}}";
}
@Singleton

View File

@ -45,8 +45,9 @@ import org.jclouds.rest.ResourceNotFoundException;
import com.google.common.base.Supplier;
import com.google.common.base.Throwables;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Sets;
import com.google.common.collect.ImmutableList.Builder;
/**
*
@ -85,6 +86,7 @@ public class StubComputeServiceAdapter implements JCloudsNativeComputeServiceAda
String id = idProvider.get() + "";
builder.ids(id);
builder.name(name);
builder.tags(template.getOptions().getTags());
builder.group(group);
builder.location(location.get());
builder.imageId(template.getImage().getId());
@ -110,18 +112,19 @@ public class StubComputeServiceAdapter implements JCloudsNativeComputeServiceAda
@Override
public Iterable<Image> listImages() {
Credentials defaultCredentials = new Credentials("root", null);
Set<Image> images = Sets.newLinkedHashSet();
// initializing as a List, as ImmutableSet does not allow you to put duplicates
Builder<Image> images = ImmutableList.<Image>builder();
int id = 1;
for (boolean is64Bit : new boolean[] { true, false })
for (Entry<OsFamily, Map<String, String>> osVersions : this.osToVersionMap.entrySet()) {
for (String version : Sets.newLinkedHashSet(osVersions.getValue().values())) {
for (String version : ImmutableSet.copyOf(osVersions.getValue().values())) {
String desc = String.format("stub %s %s", osVersions.getKey(), is64Bit);
images.add(new ImageBuilder().ids(id++ + "").name(osVersions.getKey().name()).location(location.get())
.operatingSystem(new OperatingSystem(osVersions.getKey(), desc, version, null, desc, is64Bit))
.description(desc).defaultCredentials(defaultCredentials).build());
}
}
return images;
return images.build();
}
@Override

View File

@ -105,6 +105,8 @@ public class ComputeServiceUtils {
* @return null if group cannot be parsed
*/
public static String parseGroupFromName(String from) {
if (from == null)
return null;
Matcher matcher = DELIMETED_BY_HYPHEN_ENDING_IN_HYPHEN_HEX.matcher(from);
return matcher.find() ? matcher.group(1) : null;
}

View File

@ -20,10 +20,19 @@
(ns org.jclouds.compute2-test
(:use [org.jclouds.compute2] :reload-all)
(:use clojure.test)
(:require [org.jclouds.ssh-test :as ssh-test])
(:import
org.jclouds.compute.domain.OsFamily
clojure.contrib.condition.Condition))
org.jclouds.compute.domain.OsFamily
clojure.contrib.condition.Condition
java.net.InetAddress
org.jclouds.scriptbuilder.domain.Statements
org.jclouds.compute.options.TemplateOptions
org.jclouds.compute.options.TemplateOptions$Builder
org.jclouds.compute.options.RunScriptOptions
org.jclouds.compute.options.RunScriptOptions$Builder
org.jclouds.domain.Credentials
java.util.NoSuchElementException
))
(defmacro with-private-vars [[ns fns] & tests]
"Refers private fns from ns and runs tests in context. From users mailing
@ -34,16 +43,16 @@ list, Alan Dipert and MeikelBrandmeyer."
(deftest os-families-test
(is (some #{"centos"} (map str (os-families)))))
(def *compute* (compute-service "stub" "" "" :extensions [(ssh-test/ssh-test-client ssh-test/no-op-ssh-client)]))
(defn clean-stub-fixture
"This should allow basic tests to easily be run with another service."
[compute-service]
(fn [f]
(doseq [node (nodes compute-service)]
(destroy-node (.getId node)))
(destroy-node compute-service (.getId node)))
(f)))
(def *compute* (compute-service "stub" "" ""))
(use-fixtures :each (clean-stub-fixture *compute*))
(deftest compute-service?-test
@ -54,34 +63,64 @@ list, Alan Dipert and MeikelBrandmeyer."
(is (compute-service? *compute*))
(is (compute-service? (compute-service (compute-context *compute*)))))
(defn in-group [group] #(= (.getGroup %) group))
(defn in-group? [group] #(= (.getGroup %) group))
(deftest nodes-test
(is (empty? (nodes *compute*)))
(is (create-node *compute* "fred" (build-template *compute* {} )))
(is (= 1 (count (nodes *compute*))))
(is (= 1 (count (nodes-in-group *compute* "fred"))))
;; pass in a function that selects node metadata based on NodeMetadata field
(is (= 1 (count (nodes-with-details-matching *compute* (in-group "fred")))))
(is (= 1 (count (nodes-with-details-matching *compute* (in-group? "fred")))))
;; or make your query inline
(is (= 1 (count (nodes-with-details-matching *compute* #(= (.getGroup %) "fred")))))
;; or get real fancy, and use the underlying Predicate object jclouds uses
(is (= 1 (count (nodes-with-details-matching *compute*
(reify com.google.common.base.Predicate
(apply [this input] (= (.getGroup input) "fred")))))))
(is (= 0 (count (nodes-with-details-matching *compute* (in-group "othergroup")))))
(suspend-nodes-matching *compute* (in-group "fred"))
(is (suspended? (first (nodes-with-details-matching *compute* (in-group "fred")))))
(resume-nodes-matching *compute* (in-group "fred"))
(is (= 0 (count (nodes-with-details-matching *compute* (in-group? "othergroup")))))
(suspend-nodes-matching *compute* (in-group? "fred"))
(is (suspended? (first (nodes-with-details-matching *compute* (in-group? "fred")))))
(resume-nodes-matching *compute* (in-group? "fred"))
(is (running? (first (nodes-in-group *compute* "fred"))))
(reboot-nodes-matching *compute* (in-group "fred"))
(reboot-nodes-matching *compute* (in-group? "fred"))
(is (running? (first (nodes-in-group *compute* "fred"))))
(is (create-nodes *compute* "fred" 2 (build-template *compute* {} )))
(is (= 3 (count (nodes-in-group *compute* "fred"))))
(is (= "fred" (group (first (nodes *compute*)))))
(destroy-nodes-matching *compute* (in-group "fred"))
(destroy-nodes-matching *compute* (in-group? "fred"))
(is (terminated? (first (nodes-in-group *compute* "fred")))))
(defn localhost? [node]
"Returns true if the localhost address is in the node's private ips"
(seq? (some #(= (InetAddress/getLocalHost) %) (private-ips node))))
(deftest compound-predicate-test
(is (create-node *compute* "my-group" (build-template *compute* {})))
(is (= 0 (count (nodes-with-details-matching *compute* #(and (suspended? %) (not (localhost? %)))))))
(is (= 0 (count (nodes-with-details-matching *compute* #(and (suspended? %) (localhost? %))))))
(is (= 0 (count (nodes-with-details-matching *compute* #(and (running? %) (localhost? %))))))
(is (= 1 (count (nodes-with-details-matching *compute* #(and (running? %) (not (localhost? %))))))))
(deftest run-script-on-nodes-matching-with-options-test
(let [echo (Statements/exec "echo hello")
script-options (.. (RunScriptOptions$Builder/overrideCredentialsWith (Credentials. "user" "password"))
(runAsRoot false)
(wrapInInitScript false))
pred #(= (.getGroup %) "scriptednode")]
(is (create-node *compute* "scriptednode" (build-template *compute* {})))
(is (run-script-on-nodes-matching *compute* pred echo script-options))
(is (thrown? NoSuchElementException
(run-script-on-nodes-matching *compute* #(= (.getGroup %) "nonexistingnode") echo script-options)))))
(deftest run-script-on-node-with-options-test
(let [echo (Statements/exec "echo hello")
script-options (.. (RunScriptOptions$Builder/overrideCredentialsWith (Credentials. "user" "password"))
(runAsRoot false)
(wrapInInitScript false))
test_node (create-node *compute* "scriptednode" (build-template *compute* {}))]
(is (run-script-on-node *compute* (id test_node) echo script-options))
(is (thrown? NoSuchElementException
(run-script-on-node *compute* "nonexistingnode" echo script-options)))))
(deftest build-template-test
(let [service (compute-service "stub" "user" "password")]
(testing "nullary"

View File

@ -17,6 +17,16 @@
; ====================================================================
;
(ns org.jclouds.ssh-test
(:require
[clojure.contrib.logging :as logging])
(:import
org.jclouds.ssh.SshClient
org.jclouds.domain.Credentials
org.jclouds.io.Payload
org.jclouds.net.IPSocket
org.jclouds.compute.domain.ExecResponse))
(defn instantiate [impl-class & args]
(let [constructor (first
(filter
@ -73,7 +83,12 @@
(^org.jclouds.ssh.SshClient
create
[_ ^IPSocket socket ^String username ^bytes password-or-key]
(factory-fn socket username password-or-key)))
(factory-fn socket username password-or-key))
(^org.jclouds.ssh.SshClient
create
[_ ^IPSocket socket ^Credentials credentials]
(factory-fn socket (.identity credentials) (.credential credentials)))
)
(deftype Module
[factory binder]

View File

@ -30,6 +30,7 @@ import static com.google.common.collect.Maps.uniqueIndex;
import static com.google.common.collect.Sets.filter;
import static com.google.common.collect.Sets.newTreeSet;
import static org.jclouds.compute.ComputeTestUtils.buildScript;
import static org.jclouds.compute.options.RunScriptOptions.Builder.wrapInInitScript;
import static org.jclouds.compute.options.TemplateOptions.Builder.blockOnComplete;
import static org.jclouds.compute.options.TemplateOptions.Builder.overrideCredentialsWith;
import static org.jclouds.compute.predicates.NodePredicates.TERMINATED;
@ -44,12 +45,12 @@ 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.TreeSet;
import java.util.Map.Entry;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
@ -160,8 +161,8 @@ public abstract class BaseComputeServiceLiveTest {
if (context != null)
context.close();
Properties props = setupProperties();
context = new ComputeServiceContextFactory(setupRestProperties()).createContext(provider,
ImmutableSet.of(new Log4JLoggingModule(), getSshModule()), props);
context = new ComputeServiceContextFactory(setupRestProperties()).createContext(provider, ImmutableSet.of(
new Log4JLoggingModule(), getSshModule()), props);
client = context.getComputeService();
}
@ -182,7 +183,7 @@ public abstract class BaseComputeServiceLiveTest {
ComputeServiceContext context = null;
try {
context = new ComputeServiceContextFactory(setupRestProperties()).createContext(provider, "MOMMA", "MIA",
ImmutableSet.<Module> of(new Log4JLoggingModule()));
ImmutableSet.<Module> of(new Log4JLoggingModule()));
context.getComputeService().listNodes();
} catch (AuthorizationException e) {
throw e;
@ -207,7 +208,7 @@ public abstract class BaseComputeServiceLiveTest {
@Test(enabled = true, expectedExceptions = NoSuchElementException.class)
public void testCorrectExceptionRunningNodesNotFound() throws Exception {
client.runScriptOnNodesMatching(runningInGroup("zebras-are-awesome"), buildScript(new OperatingSystem.Builder()
.family(OsFamily.UBUNTU).description("ffoo").build()));
.family(OsFamily.UBUNTU).description("ffoo").build()));
}
// since surefire and eclipse don't otherwise guarantee the order, we are
@ -231,17 +232,22 @@ public abstract class BaseComputeServiceLiveTest {
OperatingSystem os = get(nodes, 0).getOperatingSystem();
try {
Map<? extends NodeMetadata, ExecResponse> responses = runScriptWithCreds(group, os, new Credentials(
good.identity, "romeo"));
good.identity, "romeo"));
assert false : "shouldn't pass with a bad password\n" + responses;
} catch (RunScriptOnNodesException e) {
assert getRootCause(e).getMessage().contains("Auth fail") : e;
}
for (Entry<? extends NodeMetadata, ExecResponse> response : client.runScriptOnNodesMatching(
runningInGroup(group), Statements.exec("echo hello"),
overrideCredentialsWith(good).wrapInInitScript(false).runAsRoot(false)).entrySet())
runningInGroup(group), Statements.exec("echo hello"),
overrideCredentialsWith(good).wrapInInitScript(false).runAsRoot(false)).entrySet())
assert response.getValue().getOutput().trim().equals("hello") : response.getKey() + ": "
+ response.getValue();
+ response.getValue();
// test single-node execution
ExecResponse response = client.runScriptOnNode(get(nodes, 0).getId(), "echo hello", wrapInInitScript(false)
.runAsRoot(false));
assert response.getOutput().trim().equals("hello") : get(nodes, 0).getId() + ": " + response;
runScriptWithCreds(group, os, good);
@ -298,7 +304,8 @@ public abstract class BaseComputeServiceLiveTest {
// template.getOptions().installPrivateKey(keyPair.get("private")).authorizePublicKey(keyPair.get("public"))
// .runScript(buildScript(template.getImage().getOperatingSystem()));
template.getOptions().runScript(
Statements.newStatementList(AdminAccess.standard(), buildScript(template.getImage().getOperatingSystem())));
Statements.newStatementList(AdminAccess.standard(),
buildScript(template.getImage().getOperatingSystem())));
}
protected void checkImageIdMatchesTemplate(NodeMetadata node) {
@ -309,8 +316,8 @@ public abstract class BaseComputeServiceLiveTest {
protected void checkOsMatchesTemplate(NodeMetadata node) {
if (node.getOperatingSystem() != null)
assert node.getOperatingSystem().getFamily().equals(template.getImage().getOperatingSystem().getFamily()) : String
.format("expecting family %s but got %s", template.getImage().getOperatingSystem().getFamily(),
node.getOperatingSystem());
.format("expecting family %s but got %s", template.getImage().getOperatingSystem().getFamily(), node
.getOperatingSystem());
}
void assertLocationSameOrChild(Location test, Location expected) {
@ -342,10 +349,10 @@ public abstract class BaseComputeServiceLiveTest {
}
protected Map<? extends NodeMetadata, ExecResponse> runScriptWithCreds(final String group, OperatingSystem os,
Credentials creds) throws RunScriptOnNodesException {
Credentials creds) throws RunScriptOnNodesException {
try {
return client.runScriptOnNodesMatching(runningInGroup(group), buildScript(os), overrideCredentialsWith(creds)
.nameTask("runScriptWithCreds"));
.nameTask("runScriptWithCreds"));
} catch (SshException e) {
throw e;
}
@ -375,16 +382,16 @@ public abstract class BaseComputeServiceLiveTest {
@Test(enabled = true, dependsOnMethods = "testCreateAnotherNodeWithANewContextToEnsureSharedMemIsntRequired")
public void testGet() throws Exception {
Map<String, ? extends NodeMetadata> metadataMap = newLinkedHashMap(uniqueIndex(
filter(client.listNodesDetailsMatching(all()), and(inGroup(group), not(TERMINATED))),
new Function<NodeMetadata, String>() {
Map<String, ? extends NodeMetadata> metadataMap = newLinkedHashMap(uniqueIndex(filter(client
.listNodesDetailsMatching(all()), and(inGroup(group), not(TERMINATED))),
new Function<NodeMetadata, String>() {
@Override
public String apply(NodeMetadata from) {
return from.getId();
}
@Override
public String apply(NodeMetadata from) {
return from.getId();
}
}));
}));
for (NodeMetadata node : nodes) {
metadataMap.remove(node.getId());
NodeMetadata metadata = client.getNodeMetadata(node.getId());
@ -403,7 +410,7 @@ public abstract class BaseComputeServiceLiveTest {
protected void assertNodeZero(Collection<? extends NodeMetadata> metadataSet) {
assert metadataSet.size() == 0 : String.format("nodes left in set: [%s] which didn't match set: [%s]",
metadataSet, nodes);
metadataSet, nodes);
}
@Test(enabled = true, dependsOnMethods = "testGet")
@ -491,12 +498,12 @@ public abstract class BaseComputeServiceLiveTest {
}
template = client.templateBuilder().options(blockOnComplete(false).blockOnPort(8080, 600).inboundPorts(22, 8080))
.build();
.build();
// note this is a dependency on the template resolution
template.getOptions().runScript(
RunScriptData.createScriptInstallAndStartJBoss(keyPair.get("public"), template.getImage()
.getOperatingSystem()));
RunScriptData.createScriptInstallAndStartJBoss(keyPair.get("public"), template.getImage()
.getOperatingSystem()));
try {
NodeMetadata node = getOnlyElement(client.createNodesInGroup(group, 1, template));
@ -530,26 +537,26 @@ public abstract class BaseComputeServiceLiveTest {
assert location != location.getParent() : location;
assert location.getScope() != null : location;
switch (location.getScope()) {
case PROVIDER:
assertProvider(location);
break;
case REGION:
assertProvider(location.getParent());
break;
case ZONE:
Location provider = location.getParent().getParent();
// zone can be a direct descendant of provider
if (provider == null)
provider = location.getParent();
assertProvider(provider);
break;
case HOST:
Location provider2 = location.getParent().getParent().getParent();
// zone can be a direct descendant of provider
if (provider2 == null)
provider2 = location.getParent().getParent();
assertProvider(provider2);
break;
case PROVIDER:
assertProvider(location);
break;
case REGION:
assertProvider(location.getParent());
break;
case ZONE:
Location provider = location.getParent().getParent();
// zone can be a direct descendant of provider
if (provider == null)
provider = location.getParent();
assertProvider(provider);
break;
case HOST:
Location provider2 = location.getParent().getParent().getParent();
// zone can be a direct descendant of provider
if (provider2 == null)
provider2 = location.getParent().getParent();
assertProvider(provider2);
break;
}
}
}
@ -582,10 +589,10 @@ public abstract class BaseComputeServiceLiveTest {
public void testListSizes() throws Exception {
for (Hardware hardware : client.listHardwareProfiles()) {
assert hardware.getProviderId() != null;
assert getCores(hardware) > 0;
assert hardware.getVolumes().size() >= 0;
assert hardware.getRam() > 0;
assert hardware.getProviderId() != null : hardware;
assert getCores(hardware) > 0 : hardware;
assert hardware.getVolumes().size() >= 0 : hardware;
assert hardware.getRam() > 0 : hardware;
assertEquals(hardware.getType(), ComputeType.HARDWARE);
}
}
@ -637,7 +644,7 @@ public abstract class BaseComputeServiceLiveTest {
assertEquals(hello.getOutput().trim(), "hello");
ExecResponse exec = ssh.exec("java -version");
assert exec.getError().indexOf("1.6") != -1 || exec.getOutput().indexOf("1.6") != -1 : exec + "\n"
+ ssh.exec("cat /tmp/bootstrap/stdout.log /tmp/bootstrap/stderr.log");
+ ssh.exec("cat /tmp/bootstrap/stdout.log /tmp/bootstrap/stderr.log");
} finally {
if (ssh != null)
ssh.disconnect();

View File

@ -167,7 +167,7 @@ public abstract class BaseTemplateBuilderLiveTest {
Template defaultTemplate = context.getComputeService().templateBuilder().build();
Template template = context.getComputeService().templateBuilder().imageId(defaultTemplate.getImage().getId())
.build();
.locationId(defaultTemplate.getLocation().getId()).build();
assertEquals(template.getImage(), defaultTemplate.getImage());
}

View File

@ -144,11 +144,16 @@ public class StubComputeServiceIntegrationTest extends BaseComputeServiceLiveTes
runScriptAndService(client1, 1);
expect(factory.create(new IPSocket("144.175.1.2", 22), new Credentials("root", "password2"))).andReturn(
client2).times(3);
client2).times(4);
expect(factory.create(new IPSocket("144.175.1.2", 22), new Credentials("root", "romeo"))).andThrow(
new SshException("Auth fail"));
// run script without backgrounding
// run script without backgrounding (via predicate)
client2.connect();
expect(client2.exec("echo hello\n")).andReturn(new ExecResponse("hello\n", "", 0));
client2.disconnect();
// run script without backgrounding (via id)
client2.connect();
expect(client2.exec("echo hello\n")).andReturn(new ExecResponse("hello\n", "", 0));
client2.disconnect();

View File

@ -2,7 +2,7 @@
<!--
Copyright (C) 2010 Cloud Conscious, LLC.
Copyright (C) 2011 Cloud Conscious, LLC.
<info@cloudconscious.com>
====================================================================
@ -30,7 +30,7 @@
</parent>
<artifactId>jclouds-core</artifactId>
<name>jclouds Components Core</name>
<packaging>jar</packaging>
<packaging>bundle</packaging>
<description>Core components to access jclouds services</description>
<scm>
@ -105,7 +105,7 @@
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>1.6</version>
<version>1.7.1</version>
</dependency>
<dependency>
<groupId>com.google.guava</groupId>
@ -119,6 +119,43 @@
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<artifactId>maven-jar-plugin</artifactId>
<version>2.3.1</version>
<executions>
<execution>
<goals>
<goal>test-jar</goal>
</goals>
</execution>
</executions>
<configuration>
<!--
These files are excluded to avoid corrupting the classpath with ProviderMetadata implementation
classes that should only be availble when running the core tests.
-->
<excludes>
<exclude>META-INF/services/</exclude>
<exclude>org/jclouds/providers/ProvidersTest.class</exclude>
</excludes>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
<configuration>
<instructions>
<Bundle-SymbolicName>${project.artifactId}</Bundle-SymbolicName>
<Export-Package>com.google.gson;-split-package:=merge-first,
org.jclouds.*;version=${project.version}</Export-Package>
</instructions>
</configuration>
</plugin>
</plugins>
</build>
<profiles>
<profile>
<id>distribution</id>

View File

@ -23,11 +23,12 @@ import static com.google.common.base.Preconditions.checkNotNull;
import java.io.IOException;
/**
* The gson project use package to control access to their objects. However,
* this prevents us from doing valid work, like controling the json emitted on a
* per-object basis. This is here to afford us to do this.
* The gson project use package to control access to their objects. However, this prevents us from
* doing valid work, like controling the json emitted on a per-object basis. This is here to afford
* us to do this.
*
* @author Adrian Cole
* @see <a href="http://code.google.com/p/google-gson/issues/detail?id=326"/>
*/
public final class JsonLiteral extends JsonElement {
private final CharSequence literal;

View File

@ -1,89 +0,0 @@
/**
*
* Copyright (C) 2011 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* ====================================================================
*/
package com.google.gson;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Set;
import org.jclouds.json.internal.ParseObjectFromElement;
@SuppressWarnings({ "unchecked", "rawtypes" })
public class MapTypeAdapter implements JsonSerializer<Map>, JsonDeserializer<Map>, InstanceCreator<Map> {
public JsonElement serialize(Map src, Type typeOfSrc, JsonSerializationContext context) {
JsonObject map = new JsonObject();
Type childGenericType = null;
if (typeOfSrc instanceof ParameterizedType) {
childGenericType = new TypeInfoMap(typeOfSrc).getValueType();
}
for (Map.Entry entry : (Set<Map.Entry>) src.entrySet()) {
Object value = entry.getValue();
JsonElement valueElement;
if (value == null) {
valueElement = JsonNull.createJsonNull();
} else {
Type childType = (childGenericType == null) ? value.getClass() : childGenericType;
valueElement = context.serialize(value, childType);
}
map.add(String.valueOf(entry.getKey()), valueElement);
}
return map;
}
public Map deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
// Use ObjectConstructor to create instance instead of hard-coding a specific type.
// This handles cases where users are using their own subclass of Map.
Map<Object, Object> map = constructMapType(typeOfT, context);
TypeInfoMap mapTypeInfo = new TypeInfoMap(typeOfT);
for (Map.Entry<String, JsonElement> entry : json.getAsJsonObject().entrySet()) {
Object key = context.deserialize(new JsonPrimitive(entry.getKey()), mapTypeInfo.getKeyType());
// START JCLOUDS PATCH
Object value = null;
if (mapTypeInfo.getValueType() == Object.class) {
value = ParseObjectFromElement.SINGLETON.apply(entry.getValue());
}
if (value == null) {
value = context.deserialize(entry.getValue(), mapTypeInfo.getValueType());
}
// END JCLOUDS PATCH
map.put(key, value);
}
return map;
}
private Map constructMapType(Type mapType, JsonDeserializationContext context) {
JsonDeserializationContextDefault contextImpl = (JsonDeserializationContextDefault) context;
ObjectConstructor objectConstructor = contextImpl.getObjectConstructor();
return (Map) objectConstructor.construct(mapType);
}
public Map createInstance(Type type) {
return new LinkedHashMap();
}
@Override
public String toString() {
return MapTypeAdapter.class.getSimpleName();
}
}

View File

@ -0,0 +1,90 @@
/*
* Copyright (C) 2011 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.gson;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.Map;
import java.util.Set;
import org.jclouds.json.internal.ParseObjectFromElement;
import com.google.gson.internal.$Gson$Types;
/**
* Default serialization and deserialization of a map type. This implementation really only works
* well with simple primitive types as the map key. If the key is not a simple primitive then the
* object is {@code toString}ed and that value is used as its key.
* <p/>
* Patched depending on <a href="http://code.google.com/p/google-gson/issues/detail?id=325">this</a>
* @author Joel Leitch
*/
@SuppressWarnings("unchecked")
public final class ObjectMapTypeAdapter extends BaseMapTypeAdapter {
public JsonElement serialize(Map src, Type typeOfSrc, JsonSerializationContext context) {
JsonObject map = new JsonObject();
Type childGenericType = null;
if (typeOfSrc instanceof ParameterizedType) {
Class<?> rawTypeOfSrc = $Gson$Types.getRawType(typeOfSrc);
childGenericType = $Gson$Types.getMapKeyAndValueTypes(typeOfSrc, rawTypeOfSrc)[1];
}
for (Map.Entry entry : (Set<Map.Entry>) src.entrySet()) {
Object value = entry.getValue();
JsonElement valueElement;
if (value == null) {
valueElement = JsonNull.createJsonNull();
} else {
Type childType = (childGenericType == null)
? value.getClass() : childGenericType;
valueElement = serialize(context, value, childType);
}
map.add(String.valueOf(entry.getKey()), valueElement);
}
return map;
}
public Map deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context)
throws JsonParseException {
// Use ObjectConstructor to create instance instead of hard-coding a specific type.
// This handles cases where users are using their own subclass of Map.
Map<Object, Object> map = constructMapType(typeOfT, context);
Type[] keyAndValueTypes = $Gson$Types.getMapKeyAndValueTypes(typeOfT, $Gson$Types.getRawType(typeOfT));
for (Map.Entry<String, JsonElement> entry : json.getAsJsonObject().entrySet()) {
Object key = context.deserialize(new JsonPrimitive(entry.getKey()), keyAndValueTypes[0]);
// START JCLOUDS PATCH
// http://code.google.com/p/google-gson/issues/detail?id=325
Object value = null;
if (keyAndValueTypes[1] == Object.class) {
value = ParseObjectFromElement.SINGLETON.apply(entry.getValue());
}
if (value == null) {
value = context.deserialize(entry.getValue(), keyAndValueTypes[1]);
}
// END JCLOUDS PATCH
map.put(key, value);
}
return map;
}
@Override
public String toString() {
return MapTypeAdapter.class.getSimpleName();
}
}

View File

@ -1,8 +1,6 @@
/**
/*
* Copyright (C) 2010 Google Inc.
*
* Copyright (C) 2011 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
@ -14,8 +12,8 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* ====================================================================
*/
package com.google.gson;
import com.google.gson.stream.JsonReader;
@ -104,7 +102,8 @@ final class Streams {
if (serializeNulls) {
writer.nullValue();
}
//BEGIN JCLOUDS PATCH
//BEGIN JCLOUDS PATCH
// * @see <a href="http://code.google.com/p/google-gson/issues/detail?id=326"/>
} else if (element instanceof JsonLiteral ) {
writer.value(JsonLiteral.class.cast(element));
//END JCLOUDS PATCH

View File

@ -1,21 +1,19 @@
/**
/*
* Copyright (C) 2010 Google Inc.
*
* Copyright (C) 2011 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* ====================================================================
*/
package com.google.gson.stream;
import java.io.Closeable;
@ -344,7 +342,7 @@ public final class JsonWriter implements Closeable {
return this;
}
//BEGIN JCLOUDS PATCH
// * @see <a href="http://code.google.com/p/google-gson/issues/detail?id=326"/>
/**
* Writes {@code value} literally
*
@ -356,7 +354,6 @@ public final class JsonWriter implements Closeable {
return this;
}
//END JCLOUDS PATCH
/**
* Encodes {@code value}.
*

View File

@ -27,6 +27,7 @@ import org.jclouds.util.Patterns;
* As String is final, using a different marker to imply this is a json object
*
* @author Adrian Cole
* @see <a href="http://code.google.com/p/google-gson/issues/detail?id=326"/>
*/
public class JsonBall implements java.io.Serializable, Comparable<String>, CharSequence {

View File

@ -16,13 +16,14 @@
* limitations under the License.
* ====================================================================
*/
package org.jclouds.ibmdev.functions;
package org.jclouds.http.functions;
import java.util.Set;
import javax.inject.Inject;
import javax.inject.Singleton;
import org.jclouds.http.HttpResponse;
import org.jclouds.ibmdev.domain.Instance;
import com.google.common.base.Function;
import com.google.common.collect.Iterables;
@ -31,16 +32,20 @@ import com.google.common.collect.Iterables;
* @author Adrian Cole
*/
@Singleton
public class GetFirstInstanceInList implements Function<HttpResponse, Instance> {
private ParseInstancesFromJson listParser;
public class UnwrapOnlyJsonValueInSet<T> implements Function<HttpResponse, T> {
private final UnwrapOnlyJsonValue<Set<T>> json;
@Inject
public GetFirstInstanceInList(ParseInstancesFromJson mapper) {
this.listParser = mapper;
UnwrapOnlyJsonValueInSet(UnwrapOnlyJsonValue<Set<T>> json) {
this.json = json;
}
@Override
public Instance apply(HttpResponse from) {
return Iterables.getOnlyElement(listParser.apply(from));
public T apply(HttpResponse arg0) {
Set<T> set = json.apply(arg0);
if (set == null || set.size() == 0)
return null;
return Iterables.getOnlyElement(set);
}
}

View File

@ -16,34 +16,32 @@
* limitations under the License.
* ====================================================================
*/
package org.jclouds.ibmdev.functions;
package org.jclouds.io;
import java.io.InputStream;
import java.util.Map;
import javax.inject.Inject;
import javax.inject.Singleton;
import org.jclouds.http.HttpResponse;
import org.jclouds.http.functions.ParseJson;
import org.jclouds.ibmdev.domain.Image;
import org.jclouds.collect.InputSupplierMap;
import com.google.common.base.Function;
import com.google.common.annotations.Beta;
import com.google.common.io.InputSupplier;
/**
*
* @author Adrian Cole
*/
@Singleton
public class ParseImageFromJson implements Function<HttpResponse, Image> {
private final ParseJson<Image> json;
@Beta
public class CopyInputStreamInputSupplierMap extends InputSupplierMap<String, InputStream> {
@Inject
ParseImageFromJson(ParseJson<Image> json) {
this.json = json;
public CopyInputStreamInputSupplierMap(Map<String, InputSupplier<InputStream>> toMap,
CopyInputStreamIntoSupplier putFunction) {
super(toMap, putFunction);
}
@Override
public Image apply(HttpResponse arg0) {
Image input = json.apply(arg0);
ParseUtils.CLEAN_IMAGE.apply(input);
return input;
public CopyInputStreamInputSupplierMap(Map<String, InputSupplier<InputStream>> toMap) {
super(toMap, new CopyInputStreamIntoSupplier());
}
}

View File

@ -0,0 +1,64 @@
/**
*
* Copyright (C) 2011 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* ====================================================================
*/
package org.jclouds.io;
import java.io.IOException;
import java.io.InputStream;
import javax.annotation.Resource;
import org.jclouds.logging.Logger;
import com.google.common.annotations.Beta;
import com.google.common.base.Function;
import com.google.common.io.ByteStreams;
import com.google.common.io.Closeables;
import com.google.common.io.InputSupplier;
/**
*
* @author Adrian Cole
*/
@Beta
public class CopyInputStreamIntoSupplier implements Function<InputStream, InputSupplier<InputStream>> {
@Resource
protected Logger logger = Logger.NULL;
@SuppressWarnings("unchecked")
@Override
public InputSupplier<InputStream> apply(InputStream from) {
if (from == null)
return new InputSupplier<InputStream>() {
@Override
public InputStream getInput() throws IOException {
return null;
}
};
try {
return InputSupplier.class.cast(ByteStreams.newInputStreamSupplier(ByteStreams.toByteArray(from)));
} catch (Exception e) {
logger.warn(e, "ignoring problem retrieving credentials");
return null;
} finally {
Closeables.closeQuietly(from);
}
}
}

View File

@ -24,6 +24,8 @@ import java.util.Enumeration;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.inject.Inject;
import javax.inject.Singleton;
@ -36,12 +38,11 @@ import org.jclouds.json.internal.EnumTypeAdapterThatReturnsFromValue;
import org.jclouds.json.internal.GsonWrapper;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableMap.Builder;
import com.google.common.collect.Maps;
import com.google.common.collect.ImmutableMap.Builder;
import com.google.common.primitives.Bytes;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.JcloudsGsonPackageAccessor;
import com.google.gson.JsonDeserializationContext;
import com.google.gson.JsonDeserializer;
import com.google.gson.JsonElement;
@ -50,7 +51,7 @@ import com.google.gson.JsonParseException;
import com.google.gson.JsonPrimitive;
import com.google.gson.JsonSerializationContext;
import com.google.gson.JsonSerializer;
import com.google.gson.MapTypeAdapter;
import com.google.gson.ObjectMapTypeAdapter;
import com.google.gson.reflect.TypeToken;
import com.google.inject.AbstractModule;
import com.google.inject.ImplementedBy;
@ -68,12 +69,12 @@ public class GsonModule extends AbstractModule {
@Provides
@Singleton
Gson provideGson(JsonBallAdapter jsonAdapter, DateAdapter adapter, ByteListAdapter byteListAdapter,
ByteArrayAdapter byteArrayAdapter, SerializePropertiesDefaults propertiesAdapter, JsonAdapterBindings bindings)
throws ClassNotFoundException, Exception {
ByteArrayAdapter byteArrayAdapter, SerializePropertiesDefaults propertiesAdapter,
JsonAdapterBindings bindings) throws ClassNotFoundException, Exception {
GsonBuilder builder = new GsonBuilder();
JcloudsGsonPackageAccessor.registerTypeHierarchyAdapter(builder, Enum.class,
new EnumTypeAdapterThatReturnsFromValue());
JcloudsGsonPackageAccessor.registerTypeHierarchyAdapter(builder, Map.class, new MapTypeAdapter());
Logger.getLogger("com.google.gson.ParameterizedTypeHandlerMap").setLevel(Level.OFF);
builder.registerTypeHierarchyAdapter(Enum.class, new EnumTypeAdapterThatReturnsFromValue());
builder.registerTypeHierarchyAdapter(Map.class, new ObjectMapTypeAdapter());
builder.registerTypeAdapter(JsonBall.class, jsonAdapter);
builder.registerTypeAdapter(Date.class, adapter);
builder.registerTypeAdapter(Properties.class, propertiesAdapter);
@ -86,6 +87,7 @@ public class GsonModule extends AbstractModule {
return builder.create();
}
// http://code.google.com/p/google-gson/issues/detail?id=326
@ImplementedBy(JsonBallAdapterImpl.class)
public static interface JsonBallAdapter extends JsonSerializer<JsonBall>, JsonDeserializer<JsonBall> {
@ -99,7 +101,7 @@ public class GsonModule extends AbstractModule {
}
public JsonBall deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context)
throws JsonParseException {
throws JsonParseException {
return new JsonBall(json.toString());
}
@ -125,7 +127,7 @@ public class GsonModule extends AbstractModule {
@Override
public List<Byte> deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context)
throws JsonParseException {
throws JsonParseException {
return Bytes.asList(CryptoStreams.hex(json.getAsString()));
}
@ -141,7 +143,7 @@ public class GsonModule extends AbstractModule {
@Override
public byte[] deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context)
throws JsonParseException {
throws JsonParseException {
return CryptoStreams.hex(json.getAsString());
}
@ -165,7 +167,7 @@ public class GsonModule extends AbstractModule {
}
public Date deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context)
throws JsonParseException {
throws JsonParseException {
String toParse = json.getAsJsonPrimitive().getAsString();
try {
return dateService.iso8601DateParse(toParse);
@ -212,7 +214,7 @@ public class GsonModule extends AbstractModule {
}
public Date deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context)
throws JsonParseException {
throws JsonParseException {
String toParse = json.getAsJsonPrimitive().getAsString();
Date toReturn = dateService.cDateParse(toParse);
return toReturn;
@ -228,7 +230,7 @@ public class GsonModule extends AbstractModule {
}
public Date deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context)
throws JsonParseException {
throws JsonParseException {
long toParse = json.getAsJsonPrimitive().getAsLong();
if (toParse == -1)
return null;

View File

@ -27,7 +27,7 @@ import com.google.gson.JsonObject;
/**
* Exposes the JsonObject as a map so that we can use gauva apis on it.
*
* http://code.google.com/p/google-gson/issues/detail?id=325
* @author Adrian Cole
*/
public enum JsonObjectAsMap implements Function<JsonObject, Map<String, JsonElement>> {

View File

@ -24,12 +24,11 @@ import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.gson.JsonElement;
import com.google.gson.JsonPrimitive;
import com.google.gson.MapTypeAdapter;
/**
* This is a class that helps the default {@link MapTypeAdapter} make a sane object graph when the
* value is set to {@code Object}
*
* http://code.google.com/p/google-gson/issues/detail?id=325
* @author Adrian Cole
*/
public enum ParseObjectFromElement implements Function<JsonElement, Object> {

View File

@ -0,0 +1,158 @@
/**
*
* Copyright (C) 2011 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* ====================================================================
*/
package org.jclouds.providers;
import java.net.URI;
import java.util.Set;
import com.google.common.collect.ImmutableSet;
/**
* The BaseProviderMetadata class is an abstraction of {@link ProviderMetadata} to be extended by
* those implementing ProviderMetadata.
*
* (Note: This class must be abstract to allow {@link java.util.ServiceLoader} to work properly.
*
* @author Jeremy Whitlock <jwhitlock@apache.org>
*/
public abstract class BaseProviderMetadata implements ProviderMetadata {
/**
* @see java.lang.Object#hashCode()
*/
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
URI console = getConsole();
URI homepage = getHomepage();
URI docs = getApiDocumentation();
String id = getId();
String name = getName();
String identityName = getIdentityName();
String credentialName = getCredentialName();
String type = getType();
Set<String> linkedServices = getLinkedServices();
result = prime * result + ((console == null) ? 0 : console.hashCode());
result = prime * result + ((homepage == null) ? 0 : homepage.hashCode());
result = prime * result + ((docs == null) ? 0 : docs.hashCode());
result = prime * result + ((id == null) ? 0 : id.hashCode());
result = prime * result + ((name == null) ? 0 : name.hashCode());
result = prime * result + ((identityName == null) ? 0 : identityName.hashCode());
result = prime * result + ((credentialName == null) ? 0 : credentialName.hashCode());
result = prime * result + ((type == null) ? 0 : type.hashCode());
result = prime * result + ((linkedServices == null) ? 0 : linkedServices.hashCode());
return result;
}
/**
* @see java.lang.Object#equals(java.lang.Object)
*/
@Override
public boolean equals(Object obj) {
URI tConsole = getConsole();
URI tHomepage = getHomepage();
URI tDocs = getApiDocumentation();
String tId = getId();
String tName = getName();
String tIdentityName = getIdentityName();
String tCredentialName = getCredentialName();
String tType = getType();
Set<String> tLinkedServices = getLinkedServices();
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
ProviderMetadata other = (ProviderMetadata) obj;
URI oConsole = other.getConsole();
URI oHomepage = other.getHomepage();
URI oDocs = other.getApiDocumentation();
String oId = other.getId();
String oName = other.getName();
String oIdentityName = other.getIdentityName();
String oCredentialName = other.getCredentialName();
String oType = other.getType();
Set<String> oLinkedServices = other.getLinkedServices();
if (tConsole == null) {
if (oConsole != null)
return false;
} else if (!tConsole.equals(oConsole))
return false;
if (tDocs == null) {
if (oDocs != null)
return false;
} else if (!tDocs.equals(oDocs))
return false;
if (tHomepage == null) {
if (oHomepage != null)
return false;
} else if (!tHomepage.equals(oHomepage))
return false;
if (tId == null) {
if (oId != null)
return false;
} else if (!tId.equals(oId))
return false;
if (tName == null) {
if (oName != null)
return false;
} else if (!tName.equals(oName))
return false;
if (tIdentityName == null) {
if (oIdentityName != null)
return false;
} else if (!tIdentityName.equals(oIdentityName))
return false;
if (tCredentialName == null) {
if (oCredentialName != null)
return false;
} else if (!tCredentialName.equals(oCredentialName))
return false;
if (tType == null) {
if (oType != null)
return false;
} else if (!tType.equals(oType))
return false;
if (tLinkedServices == null) {
if (oLinkedServices != null)
return false;
} else if (!tLinkedServices.equals(oLinkedServices))
return false;
return true;
}
@Override
public String toString() {
return "[id=" + getId() + ", type=" + getType() + ", name=" + getName() + ", identityName=" + getIdentityName()
+ ", credentialName=" + getCredentialName() + ", homePage=" + getHomepage() + ", console="
+ getConsole() + ", apiDocs=" + getApiDocumentation() + ", linkedServices=" + getLinkedServices() + "]";
}
@Override
public Set<String> getLinkedServices() {
return ImmutableSet.of(getId());
}
}

View File

@ -19,10 +19,13 @@
package org.jclouds.providers;
import java.net.URI;
import java.util.Set;
import javax.annotation.Nullable;
/**
* The ProviderMetadata interface allows jclouds to provide a plugin framework
* for gathering cloud provider metadata.
* The ProviderMetadata interface allows jclouds to provide a plugin framework for gathering cloud
* provider metadata.
*
* @author Jeremy Whitlock <jwhitlock@apache.org>
*/
@ -30,40 +33,64 @@ public interface ProviderMetadata {
public static final String BLOBSTORE_TYPE = "blobstore";
public static final String COMPUTE_TYPE = "compute";
public static final String LOADBALANCER_TYPE = "loadbalancer";
public static final String TABLE_TYPE = "table";
public static final String QUEUE_TYPE = "queue";
/**
* Returns an identifier unique to the provider.
*
* @return the provider's unique identifier
*/
public String getId();
/**
*
* @return the provider's unique identifier
*/
public String getId();
/**
* Returns the provider type.
*
* @return the provider's type
*/
public String getType();
/**
*
* @return the provider's type
*/
public String getType();
/**
* Returns the name of the provider.
*
* @return the name (display name) of the provider
*/
public String getName();
/**
*
* @return the name (display name) of the provider
*/
public String getName();
/**
* Returns the URI to the provider's homepage.
*
* @return the url for the provider's homepage
*/
public URI getHomepage();
/**
*
* @return the name (display name) of an identity on this provider (ex. user, email, account,
* apikey)
*/
public String getIdentityName();
/**
* Returns the URI to the provider's console.
*
* @return the url for the provider's console
*/
public URI getConsole();
/**
*
* @return the name (display name) of a credential on this provider, or null if there is none
* (ex. password, secret, rsaKey)
*/
@Nullable
public String getCredentialName();
/**
*
* @return the url for the provider's homepage
*/
public URI getHomepage();
/**
*
* @return the url for the provider's console
*/
public URI getConsole();
/**
*
* @return the url for the API documentation related to this service
*/
public URI getApiDocumentation();
/**
*
* @return all known services linked to the same account on this provider
*/
public Set<String> getLinkedServices();
}

View File

@ -32,8 +32,7 @@ import java.util.ServiceLoader;
public class Providers {
/**
* Returns the providers located on the classpath via
* {@link java.util.ServiceLoader}.
* Returns the providers located on the classpath via {@link java.util.ServiceLoader}.
*
* @return all available providers loaded from classpath via ServiceLoader
*/
@ -59,10 +58,9 @@ public class Providers {
* @return the provider with the given id
*
* @throws NoSuchElementException
* whenever there are no providers with the provided id
* whenever there are no providers with the provided id
*/
public static ProviderMetadata withId(String id)
throws NoSuchElementException {
public static ProviderMetadata withId(String id) throws NoSuchElementException {
return find(all(), ProviderPredicates.id(id));
}
@ -86,6 +84,36 @@ public class Providers {
return filter(all(), ProviderPredicates.type(ProviderMetadata.COMPUTE_TYPE));
}
/**
* Returns the providers that are of type
* {@link org.jclouds.providers.ProviderMetadata#QUEUE_TYPE}.
*
* @return the queue service providers
*/
public static Iterable<ProviderMetadata> allQueue() {
return filter(all(), ProviderPredicates.type(ProviderMetadata.QUEUE_TYPE));
}
/**
* Returns the providers that are of type
* {@link org.jclouds.providers.ProviderMetadata#TABLE_TYPE}.
*
* @return the table service providers
*/
public static Iterable<ProviderMetadata> allTable() {
return filter(all(), ProviderPredicates.type(ProviderMetadata.TABLE_TYPE));
}
/**
* Returns the providers that are of type
* {@link org.jclouds.providers.ProviderMetadata#LOADBALANCER_TYPE}.
*
* @return the load balancer service providers
*/
public static Iterable<ProviderMetadata> allLoadBalancer() {
return filter(all(), ProviderPredicates.type(ProviderMetadata.LOADBALANCER_TYPE));
}
/**
* Returns the providers that are of the provided type.
*

View File

@ -20,7 +20,6 @@ package org.jclouds.rest.config;
import static com.google.common.base.Preconditions.checkNotNull;
import java.io.IOException;
import java.io.InputStream;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
@ -29,9 +28,9 @@ import javax.annotation.Resource;
import javax.inject.Inject;
import javax.inject.Singleton;
import org.jclouds.collect.InputSupplierMap;
import org.jclouds.collect.TransformingMap;
import org.jclouds.domain.Credentials;
import org.jclouds.io.CopyInputStreamInputSupplierMap;
import org.jclouds.json.Json;
import org.jclouds.logging.Logger;
import org.jclouds.rest.ConfiguresCredentialStore;
@ -39,8 +38,6 @@ import org.jclouds.util.Strings2;
import com.google.common.annotations.Beta;
import com.google.common.base.Function;
import com.google.common.io.ByteStreams;
import com.google.common.io.Closeables;
import com.google.common.io.InputSupplier;
import com.google.inject.AbstractModule;
import com.google.inject.Provides;
@ -97,48 +94,6 @@ public class CredentialStoreModule extends AbstractModule {
}
}
@Singleton
public static class CopyInputStreamInputSupplierMap extends InputSupplierMap<String, InputStream> {
@Singleton
public static class CopyInputStreamIntoSupplier implements Function<InputStream, InputSupplier<InputStream>> {
@Resource
protected Logger logger = Logger.NULL;
@SuppressWarnings("unchecked")
@Override
public InputSupplier<InputStream> apply(InputStream from) {
if (from == null)
return new InputSupplier<InputStream>() {
@Override
public InputStream getInput() throws IOException {
return null;
}
};
try {
return InputSupplier.class.cast(ByteStreams.newInputStreamSupplier(ByteStreams.toByteArray(from)));
} catch (Exception e) {
logger.warn(e, "ignoring problem retrieving credentials");
return null;
} finally {
Closeables.closeQuietly(from);
}
}
}
@Inject
public CopyInputStreamInputSupplierMap(Map<String, InputSupplier<InputStream>> toMap,
CopyInputStreamIntoSupplier putFunction) {
super(toMap, putFunction);
}
public CopyInputStreamInputSupplierMap(Map<String, InputSupplier<InputStream>> toMap) {
super(toMap, new CopyInputStreamIntoSupplier());
}
}
@Singleton
public static class CredentialsFromJsonInputStream implements Function<InputStream, Credentials> {
@Resource

View File

@ -82,6 +82,7 @@ import org.jclouds.http.functions.ReturnInputStream;
import org.jclouds.http.functions.ReturnStringIf2xx;
import org.jclouds.http.functions.ReturnTrueIf2xx;
import org.jclouds.http.functions.UnwrapOnlyJsonValue;
import org.jclouds.http.functions.UnwrapOnlyJsonValueInSet;
import org.jclouds.http.functions.UnwrapOnlyNestedJsonValue;
import org.jclouds.http.functions.UnwrapOnlyNestedJsonValueInSet;
import org.jclouds.http.functions.ParseSax.HandlerWithResult;
@ -743,34 +744,7 @@ public class RestAnnotationProcessor<T> {
|| TypeLiteral.get(method.getGenericReturnType()).equals(futureHttpResponseLiteral)) {
return Key.get((Class) IdentityFunction.class);
} else if (getAcceptHeadersOrNull(method).contains(MediaType.APPLICATION_JSON)) {
Type returnVal;
if (method.getReturnType().getTypeParameters().length == 0) {
returnVal = method.getReturnType();
} else if (method.getReturnType().equals(ListenableFuture.class)) {
ParameterizedType futureType = ((ParameterizedType) method.getGenericReturnType());
returnVal = futureType.getActualTypeArguments()[0];
if (returnVal instanceof WildcardType)
returnVal = WildcardType.class.cast(returnVal).getUpperBounds()[0];
} else {
returnVal = method.getGenericReturnType();
}
ParameterizedType parserType;
if (method.isAnnotationPresent(Unwrap.class)) {
int depth = method.getAnnotation(Unwrap.class).depth();
Class edgeCollection = method.getAnnotation(Unwrap.class).edgeCollection();
if (depth == 1 && edgeCollection == Map.class)
parserType = Types.newParameterizedType(UnwrapOnlyJsonValue.class, returnVal);
else if (depth == 2 && edgeCollection == Map.class)
parserType = Types.newParameterizedType(UnwrapOnlyNestedJsonValue.class, returnVal);
else if (depth == 3 && edgeCollection == Set.class)
parserType = Types.newParameterizedType(UnwrapOnlyNestedJsonValueInSet.class, returnVal);
else
throw new IllegalStateException(String.format(
"depth(%d) edgeCollection(%s) not yet supported for @Unwrap", depth, edgeCollection));
} else {
parserType = Types.newParameterizedType(ParseJson.class, returnVal);
}
return (Key<? extends Function<HttpResponse, ?>>) Key.get(parserType);
return getJsonParserKeyForMethod(method);
} else if (method.getReturnType().equals(String.class)
|| TypeLiteral.get(method.getGenericReturnType()).equals(futureStringLiteral)) {
return Key.get(ReturnStringIf2xx.class);
@ -784,6 +758,49 @@ public class RestAnnotationProcessor<T> {
return Key.get(annotation.value());
}
public static Key<? extends Function<HttpResponse, ?>> getJsonParserKeyForMethod(Method method) {
Type returnVal = getReturnTypeForMethod(method);
return getJsonParserKeyForMethodAnType(method, returnVal);
}
public static Type getReturnTypeForMethod(Method method) {
Type returnVal;
if (method.getReturnType().getTypeParameters().length == 0) {
returnVal = method.getReturnType();
} else if (method.getReturnType().equals(ListenableFuture.class)) {
ParameterizedType futureType = ((ParameterizedType) method.getGenericReturnType());
returnVal = futureType.getActualTypeArguments()[0];
if (returnVal instanceof WildcardType)
returnVal = WildcardType.class.cast(returnVal).getUpperBounds()[0];
} else {
returnVal = method.getGenericReturnType();
}
return returnVal;
}
@SuppressWarnings( { "unchecked", "rawtypes" })
public static Key<? extends Function<HttpResponse, ?>> getJsonParserKeyForMethodAnType(Method method, Type returnVal) {
ParameterizedType parserType;
if (method.isAnnotationPresent(Unwrap.class)) {
int depth = method.getAnnotation(Unwrap.class).depth();
Class edgeCollection = method.getAnnotation(Unwrap.class).edgeCollection();
if (depth == 1 && edgeCollection == Map.class)
parserType = Types.newParameterizedType(UnwrapOnlyJsonValue.class, returnVal);
else if (depth == 2 && edgeCollection == Map.class)
parserType = Types.newParameterizedType(UnwrapOnlyNestedJsonValue.class, returnVal);
else if (depth == 2 && edgeCollection == Set.class)
parserType = Types.newParameterizedType(UnwrapOnlyJsonValueInSet.class, returnVal);
else if (depth == 3 && edgeCollection == Set.class)
parserType = Types.newParameterizedType(UnwrapOnlyNestedJsonValueInSet.class, returnVal);
else
throw new IllegalStateException(String.format("depth(%d) edgeCollection(%s) not yet supported for @Unwrap",
depth, edgeCollection));
} else {
parserType = Types.newParameterizedType(ParseJson.class, returnVal);
}
return (Key<? extends Function<HttpResponse, ?>>) Key.get(parserType);
}
public static Class<? extends HandlerWithResult<?>> getSaxResponseParserClassOrNull(Method method) {
XMLResponseParser annotation = method.getAnnotation(XMLResponseParser.class);
if (annotation != null) {

View File

@ -126,8 +126,8 @@ openhosting-east1.contextbuilder=org.jclouds.openhosting.OpenHostingEast1Context
cloudsigma-zrh.propertiesbuilder=org.jclouds.cloudsigma.CloudSigmaZurichPropertiesBuilder
cloudsigma-zrh.contextbuilder=org.jclouds.cloudsigma.CloudSigmaContextBuilder
ibmdev.propertiesbuilder=org.jclouds.ibmdev.IBMDeveloperCloudPropertiesBuilder
ibmdev.contextbuilder=org.jclouds.ibmdev.IBMDeveloperCloudContextBuilder
ibm-smartcloud.propertiesbuilder=org.jclouds.ibm.smartcloud.IBMSmartCloudPropertiesBuilder
ibm-smartcloud.contextbuilder=org.jclouds.ibm.smartcloud.IBMSmartCloudContextBuilder
stub.contextbuilder=org.jclouds.compute.stub.StubComputeServiceContextBuilder
# example of where to change your endpoint

View File

@ -20,18 +20,24 @@ package org.jclouds.json;
import static org.testng.Assert.assertEquals;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import javax.inject.Qualifier;
import org.jclouds.http.HttpResponse;
import org.jclouds.http.functions.UnwrapOnlyNestedJsonValue;
import org.jclouds.io.Payload;
import org.jclouds.io.Payloads;
import org.jclouds.json.config.GsonModule;
import org.jclouds.rest.internal.RestAnnotationProcessor;
import org.testng.annotations.Test;
import com.google.common.base.Function;
import com.google.common.base.Throwables;
import com.google.inject.Guice;
import com.google.inject.Injector;
import com.google.inject.Key;
import com.google.inject.TypeLiteral;
import com.google.inject.util.Types;
/**
*
@ -39,22 +45,41 @@ import com.google.inject.util.Types;
*/
public abstract class BaseParserTest<T, G> {
@Retention(value = RetentionPolicy.RUNTIME)
@Target(value = { ElementType.FIELD, ElementType.PARAMETER, ElementType.METHOD })
@Qualifier
public @interface Nested {
}
@SuppressWarnings("unchecked")
protected Function<HttpResponse, T> parser(Injector i) {
try {
return (Function<HttpResponse, T>) i.getInstance(RestAnnotationProcessor.getJsonParserKeyForMethod(getClass()
.getMethod("expected")));
} catch (Exception e) {
Throwables.propagate(e);
return null;
}
}
@Test
public void test() {
T expects = expected();
Function<HttpResponse, T> parser = getParser(getInjector());
T response = parser.apply(new HttpResponse(200, "ok", Payloads.newInputStreamPayload(getClass()
.getResourceAsStream(resource()))));
Function<HttpResponse, T> parser = parser(injector());
T response = parser.apply(new HttpResponse(200, "ok", payload()));
compare(expects, response);
}
protected Payload payload() {
return Payloads.newInputStreamPayload(getClass().getResourceAsStream(resource()));
}
public void compare(T expects, T response) {
assertEquals(response.toString(), expects.toString());
}
protected Injector getInjector() {
protected Injector injector() {
return Guice.createInjector(new GsonModule() {
@Override
@ -67,15 +92,9 @@ public abstract class BaseParserTest<T, G> {
}
@SuppressWarnings("unchecked")
protected Function<HttpResponse, T> getParser(Injector i) {
return (Function<HttpResponse, T>) i.getInstance(Key.get(TypeLiteral.get(
Types.newParameterizedType(UnwrapOnlyNestedJsonValue.class, type())).getType()));
protected String resource() {
throw new IllegalStateException("please define resource such as \"/testaddresses.json\"");
}
public abstract Class<G> type();
public abstract String resource();
public abstract T expected();
}

View File

@ -22,15 +22,7 @@ import static org.testng.Assert.assertEquals;
import java.util.Set;
import org.jclouds.http.HttpResponse;
import org.jclouds.http.functions.UnwrapOnlyNestedJsonValue;
import com.google.common.base.Function;
import com.google.common.collect.ImmutableSortedSet;
import com.google.inject.Injector;
import com.google.inject.Key;
import com.google.inject.TypeLiteral;
import com.google.inject.util.Types;
/**
*
@ -38,15 +30,6 @@ import com.google.inject.util.Types;
*/
public abstract class BaseSetParserTest<T> extends BaseParserTest<Set<T>, T> {
@SuppressWarnings("unchecked")
// crazy stuff due to type erasure
@Override
protected Function<HttpResponse, Set<T>> getParser(Injector i) {
return (Function<HttpResponse, Set<T>>) i.getInstance(Key.get(TypeLiteral.get(
Types.newParameterizedType(UnwrapOnlyNestedJsonValue.class, Types
.newParameterizedType(Set.class, type()))).getType()));
}
public void compare(Set<T> expects, Set<T> response) {
assertEquals(ImmutableSortedSet.copyOf(response).toString(), ImmutableSortedSet.copyOf(expects).toString());
}

View File

@ -37,6 +37,52 @@ import com.google.inject.TypeLiteral;
public class JsonTest {
private Json json = Guice.createInjector(new GsonModule()).getInstance(Json.class);
private static class ObjectNoDefaultConstructor {
private final String stringValue;
private final int intValue;
public ObjectNoDefaultConstructor(String stringValue, int intValue) {
this.stringValue = stringValue;
this.intValue = intValue;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + intValue;
result = prime * result + ((stringValue == null) ? 0 : stringValue.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
ObjectNoDefaultConstructor other = (ObjectNoDefaultConstructor) obj;
if (intValue != other.intValue)
return false;
if (stringValue == null) {
if (other.stringValue != null)
return false;
} else if (!stringValue.equals(other.stringValue))
return false;
return true;
}
}
public void testObjectNoDefaultConstructor() {
ObjectNoDefaultConstructor obj = new ObjectNoDefaultConstructor("foo", 1);
assertEquals(json.toJson(obj), "{\"stringValue\":\"foo\",\"intValue\":1}");
ObjectNoDefaultConstructor obj2 = json.fromJson(json.toJson(obj), ObjectNoDefaultConstructor.class);
assertEquals(obj2, obj);
assertEquals(json.toJson(obj2), json.toJson(obj));
}
private static class EnumInside {
private static enum Test {
FOO, BAR;
@ -66,7 +112,7 @@ public class JsonTest {
map.put("map", ImmutableMap.of("key", "value"));
map.put("list", ImmutableList.of("key", "value"));
assertEquals(json.toJson(map),
"{\"string\":\"string\",\"map\":{\"key\":\"value\"},\"list\":[\"key\",\"value\"],\"boolean\":true,\"number\":1}");
"{\"string\":\"string\",\"map\":{\"key\":\"value\"},\"list\":[\"key\",\"value\"],\"boolean\":true,\"number\":1}");
Map<String, Object> map2 = json.fromJson(json.toJson(map), new TypeLiteral<Map<String, Object>>() {
}.getType());
assertEquals(map2, map);
@ -121,12 +167,12 @@ public class JsonTest {
public void testDeserializeEnumWithParser() {
assertEquals(json.fromJson("{enumValue : \"FOO\"}", EnumInsideWithParser.class).enumValue,
EnumInsideWithParser.Test.FOO);
EnumInsideWithParser.Test.FOO);
}
public void testDeserializeEnumWithParserAndBadValue() {
assertEquals(json.fromJson("{enumValue : \"sd\"}", EnumInsideWithParser.class).enumValue,
EnumInsideWithParser.Test.UNRECOGNIZED);
EnumInsideWithParser.Test.UNRECOGNIZED);
}
}

View File

@ -0,0 +1,73 @@
/**
*
* Copyright (C) 2011 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* ====================================================================
*/
package org.jclouds.providers;
import static org.testng.Assert.assertEquals;
import java.util.Set;
import org.testng.annotations.Test;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Iterables;
/**
*
* @author Jeremy Whitlock <jwhitlock@apache.org>
*/
@Test(groups = "unit")
public abstract class BaseProviderMetadataTest {
protected Set<String> allTypes = ImmutableSet.of(ProviderMetadata.BLOBSTORE_TYPE, ProviderMetadata.COMPUTE_TYPE,
ProviderMetadata.LOADBALANCER_TYPE, ProviderMetadata.QUEUE_TYPE, ProviderMetadata.TABLE_TYPE);
private final ProviderMetadata toTest;
private final String expectedType;
public BaseProviderMetadataTest(ProviderMetadata toTest, String expectedType) {
this.toTest = toTest;
this.expectedType = expectedType;
}
@Test
public void testWithId() {
ProviderMetadata providerMetadata = Providers.withId(toTest.getId());
assertEquals(toTest, providerMetadata);
assert providerMetadata.getLinkedServices().contains(toTest.getId());
}
// it is ok to have multiple services in the same classpath (ex. ec2 vs elb)
@Test
public void testOfTypeContains() {
ImmutableSet<ProviderMetadata> ofType = ImmutableSet.copyOf(Providers.ofType(expectedType));
assert ofType.contains(toTest) : String.format("%s not found in %s", toTest, ofType);
}
@Test
public void testAllContains() {
ImmutableSet<ProviderMetadata> all = ImmutableSet.copyOf(Providers.all());
assert all.contains(toTest) : String.format("%s not found in %s", toTest, all);
}
@Test
public void testInRestProperties() {
Iterable<String> providers = org.jclouds.rest.Providers.getSupportedProviders();
assert Iterables.contains(providers, toTest.getId()) : providers;
}
}

View File

@ -21,14 +21,14 @@ package org.jclouds.providers;
import java.net.URI;
/**
* Implementation of {@ link org.jclouds.types.ProviderMetadata} for testing.
* Implementation of @ link org.jclouds.types.ProviderMetadata} for testing.
*
* @author Jeremy Whitlock <jwhitlock@apache.org>
*/
public class JcloudsTestBlobStoreProviderMetadata implements ProviderMetadata {
public class JcloudsTestBlobStoreProviderMetadata extends BaseProviderMetadata {
/**
* {@ see org.jclouds.types.ProviderMetadata#getId()}
* {@inheritDoc}
*/
@Override
public String getId() {
@ -36,7 +36,7 @@ public class JcloudsTestBlobStoreProviderMetadata implements ProviderMetadata {
}
/**
* {@ see org.jclouds.types.ProviderMetadata#getType()}
* {@inheritDoc}
*/
@Override
public String getType() {
@ -44,7 +44,7 @@ public class JcloudsTestBlobStoreProviderMetadata implements ProviderMetadata {
}
/**
* {@ see org.jclouds.types.ProviderMetadata#getName()}
* {@inheritDoc}
*/
@Override
public String getName() {
@ -52,7 +52,23 @@ public class JcloudsTestBlobStoreProviderMetadata implements ProviderMetadata {
}
/**
* {@ see org.jclouds.types.ProviderMetadata#getHomepage()}
* {@inheritDoc}
*/
@Override
public String getCredentialName() {
return "user";
}
/**
* {@inheritDoc}
*/
@Override
public String getIdentityName() {
return "password";
}
/**
* {@inheritDoc}
*/
@Override
public URI getHomepage() {
@ -60,11 +76,19 @@ public class JcloudsTestBlobStoreProviderMetadata implements ProviderMetadata {
}
/**
* {@ see org.jclouds.types.ProviderMetadata#getConsole()}
* {@inheritDoc}
*/
@Override
public URI getConsole() {
return URI.create("http://jclouds.org/console");
}
/**
* {@inheritDoc}
*/
@Override
public URI getApiDocumentation() {
return URI.create("http://jclouds.org/documentation");
}
}

View File

@ -21,11 +21,11 @@ package org.jclouds.providers;
import java.net.URI;
/**
* Implementation of {@ link org.jclouds.types.ProviderMetadata} for testing.
* Implementation of @ link org.jclouds.types.ProviderMetadata} for testing.
*
* @author Jeremy Whitlock <jwhitlock@apache.org>
*/
public class JcloudsTestComputeProviderMetadata implements ProviderMetadata {
public class JcloudsTestComputeProviderMetadata extends BaseProviderMetadata {
/**
* {@ see org.jclouds.types.ProviderMetadata#getId()}
@ -51,6 +51,22 @@ public class JcloudsTestComputeProviderMetadata implements ProviderMetadata {
return "Test Compute Provider";
}
/**
* {@inheritDoc}
*/
@Override
public String getCredentialName() {
return "user";
}
/**
* {@inheritDoc}
*/
@Override
public String getIdentityName() {
return "password";
}
/**
* {@ see org.jclouds.types.ProviderMetadata#getHomepage()}
*/
@ -67,4 +83,12 @@ public class JcloudsTestComputeProviderMetadata implements ProviderMetadata {
return URI.create("http://jclouds.org/console");
}
/**
* {@inheritDoc}
*/
@Override
public URI getApiDocumentation() {
return URI.create("http://jclouds.org/documentation");
}
}

View File

@ -33,6 +33,9 @@ import org.testng.annotations.Test;
@Test( groups = "unit" )
public class ProvidersTest {
private final ProviderMetadata testBlobstoreProvider = new JcloudsTestBlobStoreProviderMetadata();
private final ProviderMetadata testComputeProvider = new JcloudsTestComputeProviderMetadata();
@Test
public void testWithId() {
ProviderMetadata providerMetadata;
@ -45,9 +48,9 @@ public class ProvidersTest {
; // Expected
}
providerMetadata = Providers.withId("test-blobstore-provider");
providerMetadata = Providers.withId(testBlobstoreProvider.getId());
assertEquals("Test Blobstore Provider", providerMetadata.getName());
assertEquals(testBlobstoreProvider, providerMetadata);
}
@Test
@ -55,21 +58,13 @@ public class ProvidersTest {
Iterable<ProviderMetadata> providersMetadata = Providers.ofType(ProviderMetadata.BLOBSTORE_TYPE);
for (ProviderMetadata providerMetadata : providersMetadata) {
assertEquals("Test Blobstore Provider", providerMetadata.getName());
assertEquals("test-blobstore-provider", providerMetadata.getId());
assertEquals(ProviderMetadata.BLOBSTORE_TYPE, providerMetadata.getType());
assertEquals("http://jclouds.org", providerMetadata.getHomepage().toString());
assertEquals("http://jclouds.org/console", providerMetadata.getConsole().toString());
assertEquals(testBlobstoreProvider, providerMetadata);
}
providersMetadata = Providers.ofType(ProviderMetadata.COMPUTE_TYPE);
for (ProviderMetadata providerMetadata : providersMetadata) {
assertEquals("Test Compute Provider", providerMetadata.getName());
assertEquals("test-compute-provider", providerMetadata.getId());
assertEquals(ProviderMetadata.COMPUTE_TYPE, providerMetadata.getType());
assertEquals("http://jclouds.org", providerMetadata.getHomepage().toString());
assertEquals("http://jclouds.org/console", providerMetadata.getConsole().toString());
assertEquals(testComputeProvider, providerMetadata);
}
providersMetadata = Providers.ofType("fake-type");
@ -83,16 +78,9 @@ public class ProvidersTest {
for (ProviderMetadata providerMetadata : providersMetadata) {
if (providerMetadata.getName().equals("Test Blobstore Provider")) {
assertEquals("test-blobstore-provider", providerMetadata.getId());
assertEquals(ProviderMetadata.BLOBSTORE_TYPE, providerMetadata.getType());
assertEquals("http://jclouds.org", providerMetadata.getHomepage().toString());
assertEquals("http://jclouds.org/console", providerMetadata.getConsole().toString());
assertEquals(testBlobstoreProvider, providerMetadata);
} else {
assertEquals("Test Compute Provider", providerMetadata.getName());
assertEquals("test-compute-provider", providerMetadata.getId());
assertEquals(ProviderMetadata.COMPUTE_TYPE, providerMetadata.getType());
assertEquals("http://jclouds.org", providerMetadata.getHomepage().toString());
assertEquals("http://jclouds.org/console", providerMetadata.getConsole().toString());
assertEquals(testComputeProvider, providerMetadata);
}
}
}

View File

@ -28,10 +28,10 @@ import java.util.concurrent.ConcurrentHashMap;
import org.jclouds.crypto.PemsTest;
import org.jclouds.domain.Credentials;
import org.jclouds.io.CopyInputStreamInputSupplierMap;
import org.jclouds.json.Json;
import org.jclouds.json.config.GsonModule;
import org.jclouds.rest.config.CredentialStoreModule;
import org.jclouds.rest.config.CredentialStoreModule.CopyInputStreamInputSupplierMap;
import org.jclouds.util.Strings2;
import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;
@ -46,7 +46,7 @@ import com.google.inject.TypeLiteral;
*
* @author Adrian Cole
*/
@Test(groups = "unit", sequential = true)
@Test(groups = "unit", singleThreaded = true)
public class CredentialStoreModuleTest {
Json json = createInjector().getInstance(Json.class);

View File

@ -97,6 +97,7 @@ import org.jclouds.http.functions.ReturnInputStream;
import org.jclouds.http.functions.ReturnStringIf2xx;
import org.jclouds.http.functions.ReturnTrueIf2xx;
import org.jclouds.http.functions.UnwrapOnlyJsonValue;
import org.jclouds.http.functions.UnwrapOnlyJsonValueInSet;
import org.jclouds.http.functions.UnwrapOnlyNestedJsonValue;
import org.jclouds.http.functions.UnwrapOnlyNestedJsonValueInSet;
import org.jclouds.http.internal.PayloadEnclosingImpl;
@ -834,6 +835,12 @@ public class RestAnnotationProcessorTest extends BaseRestClientTest {
@Consumes(MediaType.APPLICATION_JSON)
ListenableFuture<Long> testUnwrapDepth2Long();
@GET
@Path("/")
@Unwrap(depth = 2, edgeCollection = Set.class)
@Consumes(MediaType.APPLICATION_JSON)
ListenableFuture<String> testUnwrapDepth2Set();
@GET
@Path("/")
@Unwrap(depth = 3, edgeCollection = Set.class)
@ -1033,6 +1040,23 @@ public class RestAnnotationProcessorTest extends BaseRestClientTest {
.<String> of());
}
@SuppressWarnings("unchecked")
public void testUnwrapDepth2Set() throws SecurityException, NoSuchMethodException, IOException {
Method method = TestPut.class.getMethod("testUnwrapDepth2Set");
HttpRequest request = factory(TestPut.class).createRequest(method);
assertResponseParserClassEquals(method, request, UnwrapOnlyJsonValueInSet.class);
// now test that it works!
Function<HttpResponse, Map<String, String>> parser = (Function<HttpResponse, Map<String, String>>) RestAnnotationProcessor
.createResponseParser(parserFactory, injector, method, request);
assertEquals(parser.apply(new HttpResponse(200, "ok",
newStringPayload("{\"runit\":[\"0.7.0\"]}"))), "0.7.0");
assertEquals(parser.apply(new HttpResponse(200, "ok", newStringPayload("{\"runit\":[]}"))), null);
}
@SuppressWarnings("unchecked")
public void testUnwrapDepth2Long() throws SecurityException, NoSuchMethodException, IOException {
Method method = TestPut.class.getMethod("testUnwrapDepth2Long");

View File

@ -2,7 +2,7 @@
<!--
Copyright (C) 2010 Cloud Conscious, LLC. <info@cloudconscious.com>
Copyright (C) 2011 Cloud Conscious, LLC. <info@cloudconscious.com>
====================================================================
Licensed under the Apache License, Version 2.0 (the "License");
@ -32,7 +32,7 @@
<groupId>org.jclouds.driver</groupId>
<artifactId>jclouds-apachehc</artifactId>
<name>jclouds Apache Http Components Client</name>
<packaging>jar</packaging>
<packaging>bundle</packaging>
<description>Apache HttpComponents client</description>
<!-- bootstrapping: need to fetch the project POM -->
@ -72,4 +72,20 @@
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
<configuration>
<instructions>
<Bundle-SymbolicName>${project.artifactId}</Bundle-SymbolicName>
<Export-Package>org.jclouds.http.apachehc.*;version="${project.version}"</Export-Package>
<Import-Package>org.jclouds.*;version="${project.version}",*</Import-Package>
</instructions>
</configuration>
</plugin>
</plugins>
</build>
</project>

View File

@ -2,7 +2,7 @@
<!--
Copyright (C) 2010 Cloud Conscious, LLC. <info@cloudconscious.com>
Copyright (C) 2011 Cloud Conscious, LLC. <info@cloudconscious.com>
====================================================================
Licensed under the Apache License, Version 2.0 (the "License");
@ -33,6 +33,7 @@
<artifactId>jclouds-bouncycastle</artifactId>
<name>jclouds bouncycastle EncryptionService Module</name>
<description>jclouds bouncycastle EncryptionService Module</description>
<packaging>bundle</packaging>
<!-- bootstrapping: need to fetch the project POM -->
<repositories>
@ -65,4 +66,21 @@
<scope>compile</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
<configuration>
<instructions>
<Bundle-SymbolicName>${project.artifactId}</Bundle-SymbolicName>
<Export-Package>org.jclouds.encryption.bouncycastle.*;version="${project.version}"</Export-Package>
<Import-Package>org.jclouds.*;version="${project.version}",*</Import-Package>
</instructions>
</configuration>
</plugin>
</plugins>
</build>
</project>

Some files were not shown because too many files have changed in this diff Show More