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"); Licensed under the Apache License, Version 2.0 (the "License");
@ -28,9 +28,12 @@
<version>1.0-SNAPSHOT</version> <version>1.0-SNAPSHOT</version>
<relativePath>../../project/pom.xml</relativePath> <relativePath>../../project/pom.xml</relativePath>
</parent> </parent>
<groupId>org.jclouds.api</groupId> <groupId>org.jclouds.api</groupId>
<artifactId>atmos</artifactId> <artifactId>atmos</artifactId>
<name>jclouds atmos components</name> <name>jclouds atmos components</name>
<packaging>bundle</packaging>
<properties> <properties>
<test.initializer>org.jclouds.atmos.blobstore.integration.AtmosStorageTestInitializer</test.initializer> <test.initializer>org.jclouds.atmos.blobstore.integration.AtmosStorageTestInitializer</test.initializer>
<test.atmos.endpoint>https://accesspoint.atmos.com</test.atmos.endpoint> <test.atmos.endpoint>https://accesspoint.atmos.com</test.atmos.endpoint>
@ -38,6 +41,7 @@
<test.atmos.identity>FIXME</test.atmos.identity> <test.atmos.identity>FIXME</test.atmos.identity>
<test.atmos.credential>FIXME</test.atmos.credential> <test.atmos.credential>FIXME</test.atmos.credential>
</properties> </properties>
<dependencies> <dependencies>
<dependency> <dependency>
<groupId>org.jclouds</groupId> <groupId>org.jclouds</groupId>
@ -126,4 +130,20 @@
</profile> </profile>
</profiles> </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> </project>

View File

@ -65,6 +65,8 @@ Here are the properties:
* description - optional; long description of this node * description - optional; long description of this node
* note this is not yet in jclouds NodeMetadata * note this is not yet in jclouds NodeMetadata
* hostname - name or ip address to contact the node on * 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_arch - ex. x86
* os_family - must conform to org.jclouds.compute.domain.OsFamily in lower-hyphen format * os_family - must conform to org.jclouds.compute.domain.OsFamily in lower-hyphen format
ex. rhel, ubuntu, centos, debian, amzn-linux ex. rhel, ubuntu, centos, debian, amzn-linux
@ -96,6 +98,7 @@ nodes:
name: cluster-1 name: cluster-1
description: accounting analytics cluster description: accounting analytics cluster
hostname: cluster-1.mydomain.com hostname: cluster-1.mydomain.com
location_id: virginia
os_arch: x86 os_arch: x86
os_family: rhel os_family: rhel
os_description: redhat with CDH os_description: redhat with CDH

View File

@ -28,9 +28,12 @@
<version>1.0-SNAPSHOT</version> <version>1.0-SNAPSHOT</version>
<relativePath>../../project/pom.xml</relativePath> <relativePath>../../project/pom.xml</relativePath>
</parent> </parent>
<groupId>org.jclouds.api</groupId> <groupId>org.jclouds.api</groupId>
<artifactId>byon</artifactId> <artifactId>byon</artifactId>
<name>jclouds bring your own node provider</name> <name>jclouds bring your own node provider</name>
<packaging>bundle</packaging>
<properties> <properties>
<test.byon.endpoint>file://c:/test.txt</test.byon.endpoint> <test.byon.endpoint>file://c:/test.txt</test.byon.endpoint>
<test.byon.sudo-password> </test.byon.sudo-password> <test.byon.sudo-password> </test.byon.sudo-password>
@ -81,7 +84,7 @@
<dependency> <dependency>
<groupId>org.yaml</groupId> <groupId>org.yaml</groupId>
<artifactId>snakeyaml</artifactId> <artifactId>snakeyaml</artifactId>
<version>1.6</version> <version>1.8</version>
</dependency> </dependency>
</dependencies> </dependencies>
@ -120,4 +123,20 @@
</profile> </profile>
</profiles> </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> </project>

View File

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

View File

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

View File

@ -16,13 +16,25 @@
* limitations under the License. * 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 * @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.io.InputStream;
import java.net.URI; import java.net.URI;
import java.util.Map; import java.util.Map;
import java.util.NoSuchElementException;
import java.util.Set;
import javax.annotation.Resource; import javax.annotation.Resource;
import javax.inject.Inject; import javax.inject.Inject;
import javax.inject.Named;
import javax.inject.Singleton; import javax.inject.Singleton;
import org.jclouds.byon.Node; import org.jclouds.byon.Node;
import org.jclouds.collect.Memoized;
import org.jclouds.compute.domain.NodeMetadata; import org.jclouds.compute.domain.NodeMetadata;
import org.jclouds.compute.domain.NodeMetadataBuilder; import org.jclouds.compute.domain.NodeMetadataBuilder;
import org.jclouds.compute.domain.NodeState; 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.domain.OsFamily;
import org.jclouds.compute.reference.ComputeServiceConstants;
import org.jclouds.domain.Credentials; import org.jclouds.domain.Credentials;
import org.jclouds.domain.Location; import org.jclouds.domain.Location;
import org.jclouds.logging.Logger; import org.jclouds.logging.Logger;
import org.jclouds.util.Strings2; import org.jclouds.util.Strings2;
import com.google.common.base.Function; import com.google.common.base.Function;
import com.google.common.base.Predicate;
import com.google.common.base.Supplier; import com.google.common.base.Supplier;
import com.google.common.collect.ImmutableSet; import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Iterables;
/** /**
* @author Adrian Cole * @author Adrian Cole
@ -50,16 +57,19 @@ import com.google.common.collect.ImmutableSet;
@Singleton @Singleton
public class NodeToNodeMetadata implements Function<Node, NodeMetadata> { public class NodeToNodeMetadata implements Function<Node, NodeMetadata> {
@Resource @Resource
@Named(ComputeServiceConstants.COMPUTE_LOGGER)
protected Logger logger = Logger.NULL; protected Logger logger = Logger.NULL;
private final Supplier<Location> location; private final Supplier<Location> location;
private final Supplier<Set<? extends Location>> locations;
private final Map<String, Credentials> credentialStore; private final Map<String, Credentials> credentialStore;
private final Function<URI, InputStream> slurp; private final Function<URI, InputStream> slurp;
@Inject @Inject
NodeToNodeMetadata(Supplier<Location> location, Function<URI, InputStream> slurp, NodeToNodeMetadata(Supplier<Location> location, @Memoized Supplier<Set<? extends Location>> locations,
Map<String, Credentials> credentialStore) { Function<URI, InputStream> slurp, Map<String, Credentials> credentialStore) {
this.location = checkNotNull(location, "location"); this.location = checkNotNull(location, "location");
this.locations = checkNotNull(locations, "locations");
this.credentialStore = checkNotNull(credentialStore, "credentialStore"); this.credentialStore = checkNotNull(credentialStore, "credentialStore");
this.slurp = checkNotNull(slurp, "slurp"); this.slurp = checkNotNull(slurp, "slurp");
} }
@ -69,10 +79,10 @@ public class NodeToNodeMetadata implements Function<Node, NodeMetadata> {
NodeMetadataBuilder builder = new NodeMetadataBuilder(); NodeMetadataBuilder builder = new NodeMetadataBuilder();
builder.ids(from.getId()); builder.ids(from.getId());
builder.name(from.getName()); builder.name(from.getName());
builder.location(location.get()); builder.location(findLocationWithId(from.getLocationId()));
builder.group(from.getGroup()); builder.group(from.getGroup());
// TODO add tags! builder.tags(from.getTags());
builder.operatingSystem(new OperatingSystemBuilder().arch(from.getOsArch()).family( builder.operatingSystem(OperatingSystem.builder().arch(from.getOsArch()).family(
OsFamily.fromValue(from.getOsFamily())).description(from.getOsDescription()) OsFamily.fromValue(from.getOsFamily())).description(from.getOsDescription())
.version(from.getOsVersion()).build()); .version(from.getOsVersion()).build());
builder.state(NodeState.RUNNING); builder.state(NodeState.RUNNING);
@ -99,4 +109,24 @@ public class NodeToNodeMetadata implements Function<Node, NodeMetadata> {
builder.adminPassword(from.getSudoPassword()); builder.adminPassword(from.getSudoPassword());
return builder.build(); 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 javax.inject.Singleton;
import org.jclouds.byon.Node; import org.jclouds.byon.Node;
import org.jclouds.byon.domain.YamlNode;
import org.yaml.snakeyaml.Loader; import org.yaml.snakeyaml.Loader;
import org.yaml.snakeyaml.TypeDescription; import org.yaml.snakeyaml.TypeDescription;
import org.yaml.snakeyaml.Yaml; import org.yaml.snakeyaml.Yaml;
import org.yaml.snakeyaml.constructor.Constructor; import org.yaml.snakeyaml.constructor.Constructor;
import com.google.common.base.Function; import com.google.common.base.Function;
import com.google.common.collect.Iterables;
import com.google.common.collect.Maps; import com.google.common.collect.Maps;
/** /**
@ -44,6 +46,7 @@ import com.google.common.collect.Maps;
* name: cluster-1 * name: cluster-1
* description: xyz * description: xyz
* hostname: cluster-1.mydomain.com * hostname: cluster-1.mydomain.com
* location_id: virginia
* os_arch: x86 * os_arch: x86
* os_family: linux * os_family: linux
* os_description: redhat * os_description: redhat
@ -59,36 +62,39 @@ import com.google.common.collect.Maps;
* </pre> * </pre>
* *
* @author Kelvin Kakugawa * @author Kelvin Kakugawa
* @author Adrian Cole
*/ */
@Singleton @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 * Type-safe config class for YAML
* *
*/ */
public static class Config { public static class Config {
public List<Node> nodes; public List<YamlNode> nodes;
} }
@Override @Override
public Map<String, Node> apply(InputStream source) { public Map<String, Node> apply(InputStream source) {
Constructor constructor = new Constructor(Config.class); Constructor constructor = new Constructor(Config.class);
TypeDescription nodeDesc = new TypeDescription(Node.class); TypeDescription nodeDesc = new TypeDescription(YamlNode.class);
nodeDesc.putListPropertyType("tags", String.class); nodeDesc.putListPropertyType("tags", String.class);
constructor.addTypeDescription(nodeDesc); constructor.addTypeDescription(nodeDesc);
TypeDescription configDesc = new TypeDescription(Config.class); TypeDescription configDesc = new TypeDescription(Config.class);
configDesc.putListPropertyType("nodes", Node.class); configDesc.putListPropertyType("nodes", YamlNode.class);
constructor.addTypeDescription(configDesc); constructor.addTypeDescription(configDesc);
// note that snakeyaml also throws nosuchmethod error when you use the non-deprecated
// constructor
Yaml yaml = new Yaml(new Loader(constructor)); Yaml yaml = new Yaml(new Loader(constructor));
Config config = (Config) yaml.load(source); Config config = (Config) yaml.load(source);
checkState(config != null, "missing config: class"); checkState(config != null, "missing config: class");
checkState(config.nodes != null, "missing nodes: collection"); 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) { public String apply(Node node) {
return node.getId(); return node.getId();
} }

View File

@ -21,6 +21,7 @@ package org.jclouds.byon.internal;
import static com.google.common.base.Preconditions.checkNotNull; import static com.google.common.base.Preconditions.checkNotNull;
import java.util.Map; import java.util.Map;
import java.util.Set;
import javax.inject.Inject; import javax.inject.Inject;
import javax.inject.Singleton; import javax.inject.Singleton;
@ -34,11 +35,16 @@ import org.jclouds.compute.domain.NodeMetadata;
import org.jclouds.compute.domain.Template; import org.jclouds.compute.domain.Template;
import org.jclouds.domain.Credentials; import org.jclouds.domain.Credentials;
import org.jclouds.domain.Location; import org.jclouds.domain.Location;
import org.jclouds.domain.LocationBuilder;
import org.jclouds.domain.LocationScope;
import org.jclouds.location.suppliers.JustProvider; 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.base.Supplier;
import com.google.common.collect.ImmutableSet; import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Iterables; import com.google.common.collect.Iterables;
import com.google.common.collect.ImmutableSet.Builder;
/** /**
* *
@ -59,8 +65,8 @@ public class BYONComputeServiceAdapter implements JCloudsNativeComputeServiceAda
} }
@Override @Override
public NodeMetadata createNodeWithGroupEncodedIntoNameThenStoreCredentials(String tag, String name, Template template, public NodeMetadata createNodeWithGroupEncodedIntoNameThenStoreCredentials(String tag, String name,
Map<String, Credentials> credentialStore) { Template template, Map<String, Credentials> credentialStore) {
throw new UnsupportedOperationException(); throw new UnsupportedOperationException();
} }
@ -79,10 +85,26 @@ public class BYONComputeServiceAdapter implements JCloudsNativeComputeServiceAda
return Iterables.transform(nodes.get().values(), converter); return Iterables.transform(nodes.get().values(), converter);
} }
@SuppressWarnings("unchecked")
@Override @Override
public Iterable<Location> listLocations() { 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 @Override

View File

@ -18,16 +18,19 @@
*/ */
package org.jclouds.byon; 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 static org.testng.Assert.assertEquals;
import java.net.URI; import java.net.URI;
import java.util.Map; import java.util.Map;
import java.util.Properties; import java.util.Properties;
import org.jclouds.byon.functions.NodeToNodeMetadataTest;
import org.jclouds.byon.functions.NodesFromYamlTest; import org.jclouds.byon.functions.NodesFromYamlTest;
import org.jclouds.compute.ComputeServiceContext; import org.jclouds.compute.ComputeServiceContext;
import org.jclouds.compute.ComputeServiceContextFactory; import org.jclouds.compute.ComputeServiceContextFactory;
import org.jclouds.domain.Location;
import org.jclouds.ssh.jsch.config.JschSshClientModule; import org.jclouds.ssh.jsch.config.JschSshClientModule;
import org.testng.annotations.Test; import org.testng.annotations.Test;
@ -56,6 +59,7 @@ public class BYONComputeServiceTest {
private void assertNodesParse(String endpoint) { private void assertNodesParse(String endpoint) {
ComputeServiceContext context = null; ComputeServiceContext context = null;
try { try {
Location providerLocation = expectedProviderLocationFromResource(endpoint);
Properties props = new Properties(); Properties props = new Properties();
props.setProperty("byon.endpoint", endpoint); props.setProperty("byon.endpoint", endpoint);
@ -69,12 +73,45 @@ public class BYONComputeServiceTest {
.getApi(); .getApi();
assertEquals(supplier.get().size(), context.getComputeService().listNodes().size()); 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)); NodesFromYamlTest.TEST1));
assertEquals(context.getComputeService().listNodes(), ImmutableSet.of(NodeToNodeMetadataTest assertEquals(context.getComputeService().listNodes(), ImmutableSet
.expectedNodeMetadataFromResource(endpoint))); .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 { } finally {
if (context != null) if (context != null)
context.close(); 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.net.URI;
import java.util.Map; import java.util.Map;
import java.util.Set;
import org.jclouds.byon.suppliers.SupplyFromProviderURIOrNodesProperty; import org.jclouds.byon.suppliers.SupplyFromProviderURIOrNodesProperty;
import org.jclouds.compute.domain.NodeMetadata; import org.jclouds.compute.domain.NodeMetadata;
import org.jclouds.compute.domain.NodeMetadataBuilder; import org.jclouds.compute.domain.NodeMetadataBuilder;
import org.jclouds.compute.domain.NodeState; 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.domain.OsFamily;
import org.jclouds.domain.Credentials; import org.jclouds.domain.Credentials;
import org.jclouds.domain.Location; import org.jclouds.domain.Location;
@ -45,31 +46,51 @@ import com.google.common.collect.Maps;
* @author Adrian Cole * @author Adrian Cole
*/ */
public class NodeToNodeMetadataTest { 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(); return new LocationBuilder().scope(LocationScope.PROVIDER).id("byon").description(resource).build();
} }
public static NodeMetadata expectedNodeMetadataFromResource(String resource) { public static Location zoneCalled(String zone, Location parent) {
Location location = expectedLocationFromResource(resource); 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( String resource = "location";
NodeState.RUNNING).operatingSystem(
new OperatingSystemBuilder().description("redhat").family(OsFamily.RHEL).arch("x86").version("5.3") Location provider = expectedProviderLocationFromResource(resource);
.build()).publicAddresses(ImmutableSet.of("cluster-1.mydomain.com")).credentials(
new Credentials("myUser", NodesFromYamlTest.key)).adminPassword("happy bear").build(); 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 @Test
public void testNodesParse() throws Exception { public void testNodesParse() throws Exception {
assertEquals(parser.apply(NodesFromYamlTest.TEST1), expectedNodeMetadataFromResource(resource, provider));
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(credentialStore, ImmutableMap.of("node#cluster-1", new Credentials("myUser", NodesFromYamlTest.key))); 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(); .toString();
public static final Node TEST1 = new Node("cluster-1", "cluster-1", "accounting analytics cluster", public static final Node TEST1 = new Node("cluster-1", "cluster-1", "accounting analytics cluster",
"cluster-1.mydomain.com", "x86", "rhel", "redhat", "5.3", "hadoop", ImmutableList.of("vanilla"), "myUser", "cluster-1.mydomain.com", null, "x86", "rhel", "redhat", "5.3", false, "hadoop", ImmutableList.of("vanilla"),
key, null, "happy bear"); "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 @Test
public void testNodesParse() throws Exception { public void testNodesParse() throws Exception {
InputStream is = getClass().getResourceAsStream("/test1.yaml"); InputStream is = getClass().getResourceAsStream("/test1.yaml");
NodesFromYaml parser = new NodesFromYaml(); NodesFromYamlStream parser = new NodesFromYamlStream();
assertEquals(parser.apply(is), ImmutableMap.of(TEST1.getId(), TEST1)); 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 @Test
public void testNodesParseWhenCredentialInUrl() throws Exception { public void testNodesParseWhenCredentialInUrl() throws Exception {
InputStream is = getClass().getResourceAsStream("/test_with_url.yaml"); 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)); assertEquals(parser.apply(is), ImmutableMap.of(TEST1.getId(), TEST1));
} }
@Test(expectedExceptions = IllegalStateException.class) @Test(expectedExceptions = IllegalStateException.class)
public void testMustParseSomething() throws Exception { 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; package org.jclouds.byon.suppliers;
import org.jclouds.byon.functions.NodesFromYaml; import org.jclouds.byon.functions.NodesFromYamlStream;
import org.jclouds.util.Strings2; import org.jclouds.util.Strings2;
import org.testng.annotations.Test; import org.testng.annotations.Test;
@ -33,7 +33,7 @@ public class NodesParsedFromSupplierTest {
@Test(expectedExceptions = IllegalStateException.class) @Test(expectedExceptions = IllegalStateException.class)
public void testMustParseSomething() throws Exception { 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> <artifactId>cloudfiles</artifactId>
<name>jcloud cloudfiles api</name> <name>jcloud cloudfiles api</name>
<description>jclouds components to access an implementation of CloudFiles</description> <description>jclouds components to access an implementation of CloudFiles</description>
<packaging>bundle</packaging>
<properties> <properties>
<test.initializer>org.jclouds.cloudfiles.blobstore.integration.CloudFilesTestInitializer</test.initializer> <test.initializer>org.jclouds.cloudfiles.blobstore.integration.CloudFilesTestInitializer</test.initializer>
@ -145,6 +146,21 @@
</profile> </profile>
</profiles> </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> </project>

View File

@ -29,10 +29,12 @@
<version>1.0-SNAPSHOT</version> <version>1.0-SNAPSHOT</version>
<relativePath>../../project/pom.xml</relativePath> <relativePath>../../project/pom.xml</relativePath>
</parent> </parent>
<groupId>org.jclouds.api</groupId> <groupId>org.jclouds.api</groupId>
<artifactId>cloudservers</artifactId> <artifactId>cloudservers</artifactId>
<name>jcloud cloudservers api</name> <name>jcloud cloudservers api</name>
<description>jclouds components to access an implementation of CloudServers</description> <description>jclouds components to access an implementation of CloudServers</description>
<packaging>bundle</packaging>
<properties> <properties>
<test.cloudservers.endpoint>https://auth.api.rackspacecloud.com</test.cloudservers.endpoint> <test.cloudservers.endpoint>https://auth.api.rackspacecloud.com</test.cloudservers.endpoint>
@ -145,6 +147,21 @@
</profile> </profile>
</profiles> </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> </project>

View File

@ -34,6 +34,7 @@
<artifactId>deltacloud</artifactId> <artifactId>deltacloud</artifactId>
<name>jclouds deltacloud core</name> <name>jclouds deltacloud core</name>
<description>jclouds components to access deltacloud</description> <description>jclouds components to access deltacloud</description>
<packaging>bundle</packaging>
<!-- bootstrapping: need to fetch the project POM --> <!-- bootstrapping: need to fetch the project POM -->
<repositories> <repositories>
@ -141,4 +142,21 @@
</build> </build>
</profile> </profile>
</profiles> </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> </project>

View File

@ -33,6 +33,7 @@
<artifactId>ec2</artifactId> <artifactId>ec2</artifactId>
<name>jcloud ec2 api</name> <name>jcloud ec2 api</name>
<description>jclouds components to access an implementation of EC2</description> <description>jclouds components to access an implementation of EC2</description>
<packaging>bundle</packaging>
<properties> <properties>
<!-- when instances are hung, open a ticket and add here --> <!-- when instances are hung, open a ticket and add here -->
@ -142,6 +143,21 @@
</profile> </profile>
</profiles> </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> </project>

View File

@ -25,20 +25,20 @@
(:use (clojure.contrib def core)) (:use (clojure.contrib def core))
(:import org.jclouds.aws.domain.Region (:import org.jclouds.aws.domain.Region
org.jclouds.compute.domain.NodeMetadata org.jclouds.compute.domain.NodeMetadata
(org.jclouds.aws.ec2.domain Volume Volume$Status Snapshot Snapshot$Status AvailabilityZone) (org.jclouds.ec2.domain Volume Volume$Status Snapshot Snapshot$Status AvailabilityZoneInfo)
(org.jclouds.aws.ec2.options DescribeSnapshotsOptions DetachVolumeOptions CreateSnapshotOptions))) (org.jclouds.ec2.options DescribeSnapshotsOptions DetachVolumeOptions CreateSnapshotOptions)))
(defn snapshot? (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] [s]
(instance? Snapshot s)) (instance? Snapshot s))
(defn volume? (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] [v]
(instance? Volume v)) (instance? Volume v))
(defn #^org.jclouds.aws.ec2.services.ElasticBlockStoreClient (defn #^org.jclouds.ec2.services.ElasticBlockStoreClient
ebs-service ebs-service
"Returns the synchronous ElasticBlockStoreClient associated with "Returns the synchronous ElasticBlockStoreClient associated with
the specified compute service, or compute/*compute* as bound by with-compute-service." 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)))))) (str "Can't obtain volume id from argument of type " (class v))))))
(defn volumes (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). volumes in the specified region (defaulting to your account's default region).
e.g. (with-compute-service [compute] (volumes)) e.g. (with-compute-service [compute] (volumes))
@ -172,7 +172,7 @@
(defn get-zone (defn get-zone
[v] [v]
(cond (cond
(instance? AvailabilityZone v) v (instance? AvailabilityZoneInfo v) (.getZone v)
(instance? NodeMetadata v) (compute/location #^NodeMetadata v) (instance? NodeMetadata v) (compute/location #^NodeMetadata v)
(string? v) v (string? v) v
(keyword? v) (name v) (keyword? v) (name v)
@ -225,14 +225,14 @@
(defn create-volume (defn create-volume
"Creates a new volume given a set of options: "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 - one or both of :snapshot (keyword, string, or Snapshot instance) or :size
(string, keyword, or number) (string, keyword, or number)
- :device (string or keyword) provided *only* when you want to attach the new volume to - :device (string or keyword) provided *only* when you want to attach the new volume to
the :node you specified! the :node you specified!
Returns a vector of [created org.jclouds.aws.ec2.domain.Volume, Returns a vector of [created org.jclouds.ec2.domain.Volume,
optional org.jclouds.aws.ec2.domain.Attachment] optional org.jclouds.ec2.domain.Attachment]
Note that specifying :node instead of :zone will only attach the created volume 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 :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."} :doc "A clojure binding for the jclouds AWS elastic IP address interface."}
org.jclouds.ec2.elastic-ip org.jclouds.ec2.elastic-ip
(:require (org.jclouds [compute :as compute]) (:require (org.jclouds [compute :as compute])
[org.jclouds.aws.ebs :as ebs]) [org.jclouds.ec2.ebs :as ebs])
(:use (clojure.contrib def core)) (:use (clojure.contrib def core))
(:import org.jclouds.compute.domain.NodeMetadata (: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 eip-service
"Returns the synchronous ElasticIPAddressClient associated with "Returns the synchronous ElasticIPAddressClient associated with
the specified compute service, or compute/*compute* as bound by with-compute-service." 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.aws.util.AWSUtils;
import org.jclouds.collect.Memoized; import org.jclouds.collect.Memoized;
import org.jclouds.compute.ComputeServiceContext; import org.jclouds.compute.ComputeServiceContext;
import org.jclouds.compute.callables.RunScriptOnNode;
import org.jclouds.compute.domain.Hardware; import org.jclouds.compute.domain.Hardware;
import org.jclouds.compute.domain.Image; import org.jclouds.compute.domain.Image;
import org.jclouds.compute.domain.NodeMetadata; import org.jclouds.compute.domain.NodeMetadata;
@ -91,14 +92,16 @@ public class EC2ComputeService extends BaseComputeService {
@Named("NODE_RUNNING") Predicate<NodeMetadata> nodeRunning, @Named("NODE_RUNNING") Predicate<NodeMetadata> nodeRunning,
@Named("NODE_TERMINATED") Predicate<NodeMetadata> nodeTerminated, @Named("NODE_TERMINATED") Predicate<NodeMetadata> nodeTerminated,
@Named("NODE_SUSPENDED") Predicate<NodeMetadata> nodeSuspended, @Named("NODE_SUSPENDED") Predicate<NodeMetadata> nodeSuspended,
InitializeRunScriptOnNodeOrPlaceInBadMap.Factory initScriptRunnerFactory, InitAdminAccess initAdminAccess, InitializeRunScriptOnNodeOrPlaceInBadMap.Factory initScriptRunnerFactory,
RunScriptOnNode.Factory runScriptOnNodeFactory, InitAdminAccess initAdminAccess,
PersistNodeCredentials persistNodeCredentials, Timeouts timeouts, PersistNodeCredentials persistNodeCredentials, Timeouts timeouts,
@Named(Constants.PROPERTY_USER_THREADS) ExecutorService executor, EC2Client ec2Client, @Named(Constants.PROPERTY_USER_THREADS) ExecutorService executor, EC2Client ec2Client,
Map<RegionAndName, KeyPair> credentialsMap, @Named("SECURITY") Map<RegionAndName, String> securityGroupMap) { Map<RegionAndName, KeyPair> credentialsMap, @Named("SECURITY") Map<RegionAndName, String> securityGroupMap) {
super(context, credentialStore, images, sizes, locations, listNodesStrategy, getNodeMetadataStrategy, super(context, credentialStore, images, sizes, locations, listNodesStrategy, getNodeMetadataStrategy,
runNodesAndAddToSetStrategy, rebootNodeStrategy, destroyNodeStrategy, startNodeStrategy, stopNodeStrategy, runNodesAndAddToSetStrategy, rebootNodeStrategy, destroyNodeStrategy, startNodeStrategy, stopNodeStrategy,
templateBuilderProvider, templateOptionsProvider, nodeRunning, nodeTerminated, nodeSuspended, templateBuilderProvider, templateOptionsProvider, nodeRunning, nodeTerminated, nodeSuspended,
initScriptRunnerFactory, initAdminAccess, persistNodeCredentials, timeouts, executor); initScriptRunnerFactory, initAdminAccess, runScriptOnNodeFactory, persistNodeCredentials, timeouts,
executor);
this.ec2Client = ec2Client; this.ec2Client = ec2Client;
this.credentialsMap = credentialsMap; this.credentialsMap = credentialsMap;
this.securityGroupMap = securityGroupMap; this.securityGroupMap = securityGroupMap;

View File

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

View File

@ -34,6 +34,7 @@
<artifactId>elasticstack</artifactId> <artifactId>elasticstack</artifactId>
<name>jclouds elasticstack core</name> <name>jclouds elasticstack core</name>
<description>jclouds components to access elasticstack</description> <description>jclouds components to access elasticstack</description>
<packaging>bundle</packaging>
<!-- bootstrapping: need to fetch the project POM --> <!-- bootstrapping: need to fetch the project POM -->
<repositories> <repositories>
@ -147,4 +148,20 @@
</build> </build>
</profile> </profile>
</profiles> </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> </project>

View File

@ -33,6 +33,7 @@
<artifactId>eucalyptus</artifactId> <artifactId>eucalyptus</artifactId>
<name>jclouds Eucalyptus api</name> <name>jclouds Eucalyptus api</name>
<description>EC2 implementation based on Eucalyptus</description> <description>EC2 implementation based on Eucalyptus</description>
<packaging>bundle</packaging>
<properties> <properties>
<test.eucalyptus.endpoint>http://ecc.eucalyptus.com:8773/services/Eucalyptus</test.eucalyptus.endpoint> <test.eucalyptus.endpoint>http://ecc.eucalyptus.com:8773/services/Eucalyptus</test.eucalyptus.endpoint>
@ -136,6 +137,21 @@
</profile> </profile>
</profiles> </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> </project>

View File

@ -33,6 +33,7 @@
<artifactId>filesystem</artifactId> <artifactId>filesystem</artifactId>
<name>jcloud filesystem core</name> <name>jcloud filesystem core</name>
<description>jclouds components to access filesystem</description> <description>jclouds components to access filesystem</description>
<packaging>bundle</packaging>
<dependencies> <dependencies>
<dependency> <dependency>
@ -72,5 +73,21 @@
<test.initializer>org.jclouds.filesystem.integration.FilesystemTestInitializer</test.initializer> <test.initializer>org.jclouds.filesystem.integration.FilesystemTestInitializer</test.initializer>
</properties> </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> </project>

View File

@ -33,6 +33,7 @@
<artifactId>nova</artifactId> <artifactId>nova</artifactId>
<name>jcloud nova api</name> <name>jcloud nova api</name>
<description>jclouds components to access an implementation of OpenStack Nova</description> <description>jclouds components to access an implementation of OpenStack Nova</description>
<packaging>bundle</packaging>
<properties> <properties>
@ -96,22 +97,6 @@
</dependency> </dependency>
</dependencies> </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> <profiles>
<profile> <profile>
<id>live</id> <id>live</id>
@ -175,5 +160,20 @@
</profile> </profile>
</profiles> </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> </project>

View File

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

View File

@ -33,6 +33,7 @@
<artifactId>s3</artifactId> <artifactId>s3</artifactId>
<name>jcloud s3 api</name> <name>jcloud s3 api</name>
<description>jclouds components to access an implementation of S3</description> <description>jclouds components to access an implementation of S3</description>
<packaging>bundle</packaging>
<properties> <properties>
<test.initializer>org.jclouds.s3.blobstore.integration.S3TestInitializer</test.initializer> <test.initializer>org.jclouds.s3.blobstore.integration.S3TestInitializer</test.initializer>
@ -143,6 +144,21 @@
</profile> </profile>
</profiles> </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> </project>

View File

@ -33,6 +33,7 @@
<artifactId>scality-rs2</artifactId> <artifactId>scality-rs2</artifactId>
<name>jclouds Eucalyptus Walrus api</name> <name>jclouds Eucalyptus Walrus api</name>
<description>Simple Storage Service (S3) implementation based on Scality RING RS2</description> <description>Simple Storage Service (S3) implementation based on Scality RING RS2</description>
<packaging>bundle</packaging>
<properties> <properties>
<test.initializer>org.jclouds.scality.rs2.blobstore.ScalityRS2TestInitializer</test.initializer> <test.initializer>org.jclouds.scality.rs2.blobstore.ScalityRS2TestInitializer</test.initializer>
@ -139,6 +140,21 @@
</profile> </profile>
</profiles> </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> </project>

View File

@ -33,6 +33,7 @@
<artifactId>swift</artifactId> <artifactId>swift</artifactId>
<name>jcloud swift api</name> <name>jcloud swift api</name>
<description>jclouds components to access an implementation of OpenStack Swift</description> <description>jclouds components to access an implementation of OpenStack Swift</description>
<packaging>bundle</packaging>
<properties> <properties>
<test.initializer>org.jclouds.openstack.swift.blobstore.integration.SwiftTestInitializer</test.initializer> <test.initializer>org.jclouds.openstack.swift.blobstore.integration.SwiftTestInitializer</test.initializer>
@ -143,6 +144,21 @@
</profile> </profile>
</profiles> </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> </project>

View File

@ -32,6 +32,7 @@
<artifactId>vcloud</artifactId> <artifactId>vcloud</artifactId>
<name>jcloud vcloud api</name> <name>jcloud vcloud api</name>
<description>jclouds components to access an implementation of VMWare vCloud</description> <description>jclouds components to access an implementation of VMWare vCloud</description>
<packaging>bundle</packaging>
<properties> <properties>
<!-- when instances are hung, open a ticket and add here --> <!-- when instances are hung, open a ticket and add here -->
@ -156,4 +157,20 @@
</profile> </profile>
</profiles> </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> </project>

View File

@ -32,6 +32,7 @@
<artifactId>vcloudexpress</artifactId> <artifactId>vcloudexpress</artifactId>
<name>jcloud vcloudexpress api</name> <name>jcloud vcloudexpress api</name>
<description>jclouds components to access an implementation of VMWare vCloud Express</description> <description>jclouds components to access an implementation of VMWare vCloud Express</description>
<packaging>bundle</packaging>
<properties> <properties>
<!-- when instances are hung, open a ticket and add here --> <!-- when instances are hung, open a ticket and add here -->
@ -156,4 +157,20 @@
</profile> </profile>
</profiles> </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> </project>

View File

@ -33,6 +33,7 @@
<artifactId>walrus</artifactId> <artifactId>walrus</artifactId>
<name>jclouds Eucalyptus Walrus api</name> <name>jclouds Eucalyptus Walrus api</name>
<description>Simple Storage Service (S3) implementation based on Eucalyptus Walrus</description> <description>Simple Storage Service (S3) implementation based on Eucalyptus Walrus</description>
<packaging>bundle</packaging>
<properties> <properties>
<test.initializer>org.jclouds.walrus.blobstore.WalrusTestInitializer</test.initializer> <test.initializer>org.jclouds.walrus.blobstore.WalrusTestInitializer</test.initializer>
@ -139,6 +140,21 @@
</profile> </profile>
</profiles> </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> </project>

View File

@ -32,6 +32,7 @@
<artifactId>jclouds-blobstore</artifactId> <artifactId>jclouds-blobstore</artifactId>
<name>jclouds blobstore core</name> <name>jclouds blobstore core</name>
<description>jclouds components to access blobstore</description> <description>jclouds components to access blobstore</description>
<packaging>bundle</packaging>
<scm> <scm>
<connection>scm:svn:http://jclouds.googlecode.com/svn/trunk/blobstore</connection> <connection>scm:svn:http://jclouds.googlecode.com/svn/trunk/blobstore</connection>
@ -118,6 +119,18 @@
</excludes> </excludes>
</configuration> </configuration>
</plugin> </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> </plugins>
</build> </build>
</project> </project>

View File

@ -32,6 +32,8 @@
<artifactId>aws-common</artifactId> <artifactId>aws-common</artifactId>
<name>jclouds Amazon AWS Components Core</name> <name>jclouds Amazon AWS Components Core</name>
<description>jclouds Core components to access Amazon AWS</description> <description>jclouds Core components to access Amazon AWS</description>
<packaging>bundle</packaging>
<dependencies> <dependencies>
<dependency> <dependency>
<groupId>org.jclouds</groupId> <groupId>org.jclouds</groupId>
@ -47,4 +49,20 @@
</dependency> </dependency>
</dependencies> </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> </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"); Licensed under the Apache License, Version 2.0 (the "License");
@ -32,6 +32,8 @@
<artifactId>azure-common</artifactId> <artifactId>azure-common</artifactId>
<name>jclouds Azure Components Core</name> <name>jclouds Azure Components Core</name>
<description>jclouds Core components to access Azure</description> <description>jclouds Core components to access Azure</description>
<packaging>bundle</packaging>
<dependencies> <dependencies>
<dependency> <dependency>
<groupId>org.jclouds</groupId> <groupId>org.jclouds</groupId>
@ -47,4 +49,20 @@
</dependency> </dependency>
</dependencies> </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> </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"); Licensed under the Apache License, Version 2.0 (the "License");
@ -28,10 +28,13 @@
<version>1.0-SNAPSHOT</version> <version>1.0-SNAPSHOT</version>
<relativePath>../../project/pom.xml</relativePath> <relativePath>../../project/pom.xml</relativePath>
</parent> </parent>
<groupId>org.jclouds.common</groupId> <groupId>org.jclouds.common</groupId>
<artifactId>openstack-common</artifactId> <artifactId>openstack-common</artifactId>
<name>jclouds Rackspace Components Core</name> <name>jclouds OpenStack Components Core</name>
<description>jclouds Core components to access Rackspace apis</description> <description>jclouds Core components to access OpenStack apis</description>
<packaging>bundle</packaging>
<dependencies> <dependencies>
<dependency> <dependency>
<groupId>org.jclouds</groupId> <groupId>org.jclouds</groupId>
@ -47,4 +50,20 @@
</dependency> </dependency>
</dependencies> </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> </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"); Licensed under the Apache License, Version 2.0 (the "License");
@ -28,10 +28,13 @@
<version>1.0-SNAPSHOT</version> <version>1.0-SNAPSHOT</version>
<relativePath>../../project/pom.xml</relativePath> <relativePath>../../project/pom.xml</relativePath>
</parent> </parent>
<groupId>org.jclouds.common</groupId> <groupId>org.jclouds.common</groupId>
<artifactId>trmk-common</artifactId> <artifactId>trmk-common</artifactId>
<name>common Terremark components</name> <name>common Terremark components</name>
<description>common Terremark components</description> <description>common Terremark components</description>
<packaging>bundle</packaging>
<dependencies> <dependencies>
<dependency> <dependency>
<groupId>org.jclouds.api</groupId> <groupId>org.jclouds.api</groupId>
@ -91,4 +94,20 @@
</dependency> </dependency>
</dependencies> </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> </project>

View File

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

View File

@ -28,10 +28,13 @@
<version>1.0-SNAPSHOT</version> <version>1.0-SNAPSHOT</version>
<relativePath>../../project/pom.xml</relativePath> <relativePath>../../project/pom.xml</relativePath>
</parent> </parent>
<groupId>org.jclouds.common</groupId> <groupId>org.jclouds.common</groupId>
<artifactId>vcloud-common</artifactId> <artifactId>vcloud-common</artifactId>
<name>common vCloud components</name> <name>common vCloud components</name>
<description>common vCloud components</description> <description>common vCloud components</description>
<packaging>bundle</packaging>
<dependencies> <dependencies>
<dependency> <dependency>
<groupId>com.jamesmurty.utils</groupId> <groupId>com.jamesmurty.utils</groupId>
@ -82,4 +85,19 @@
</dependency> </dependency>
</dependencies> </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> </project>

View File

@ -28,7 +28,6 @@ import java.util.regex.Pattern;
import javax.inject.Inject; import javax.inject.Inject;
import javax.inject.Provider; import javax.inject.Provider;
import javax.inject.Singleton; import javax.inject.Singleton;
import javax.ws.rs.core.HttpHeaders;
import org.jclouds.http.HttpResponse; import org.jclouds.http.HttpResponse;
import org.jclouds.http.HttpResponseException; import org.jclouds.http.HttpResponseException;
@ -49,36 +48,35 @@ import com.google.common.base.Function;
*/ */
@Singleton @Singleton
public class ParseLoginResponseFromHeaders implements Function<HttpResponse, VCloudSession> { 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 ParseSax.Factory factory;
private final Provider<OrgListHandler> orgHandlerProvider; private final Provider<OrgListHandler> orgHandlerProvider;
@Inject @Inject
private ParseLoginResponseFromHeaders(Factory factory, private ParseLoginResponseFromHeaders(Factory factory, Provider<OrgListHandler> orgHandlerProvider) {
Provider<OrgListHandler> orgHandlerProvider) {
this.factory = factory; this.factory = factory;
this.orgHandlerProvider = orgHandlerProvider; 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) { public VCloudSession apply(HttpResponse from) {
String cookieHeader = checkNotNull(from.getFirstHeaderOrNull(HttpHeaders.SET_COOKIE), String cookieHeader = checkNotNull(from.getFirstHeaderOrNull("x-vcloud-authorization"), "x-vcloud-authorization");
HttpHeaders.SET_COOKIE);
final Matcher matcher = pattern.matcher(cookieHeader); final Matcher matcher = pattern.matcher(cookieHeader);
boolean matchFound = matcher.find(); boolean matchFound = matcher.find();
try { try {
if (matchFound) { if (matchFound) {
final Map<String, ReferenceType> org = factory.create(orgHandlerProvider.get()).parse( final Map<String, ReferenceType> org = factory.create(orgHandlerProvider.get()).parse(
from.getPayload().getInput()); from.getPayload().getInput());
return new VCloudSession() { return new VCloudSession() {
@VCloudToken @VCloudToken
public String getVCloudToken() { public String getVCloudToken() {
return matcher.group(1); return matcher.group(2);
} }
@Org @Org
@ -91,6 +89,6 @@ public class ParseLoginResponseFromHeaders implements Function<HttpResponse, VCl
} finally { } finally {
releasePayload(from); 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; package org.jclouds.vcloud.xml;
import static org.jclouds.util.SaxUtils.equalsOrSuffix;
import static org.jclouds.vcloud.util.Utils.newReferenceType; import static org.jclouds.vcloud.util.Utils.newReferenceType;
import java.util.List; import java.util.List;
@ -271,11 +272,11 @@ public class OrgNetworkHandler extends ParseSax.HandlerWithResult<OrgNetwork> {
this.vmNicId = -1; this.vmNicId = -1;
} else if (qName.equalsIgnoreCase("ExternalPort")) { } else if (qName.equalsIgnoreCase("ExternalPort")) {
externalPort = Integer.parseInt(currentOrNull()); externalPort = Integer.parseInt(currentOrNull());
} else if (qName.equalsIgnoreCase("IxternalIP")) { } else if (qName.equalsIgnoreCase("InternalIP")) {
internalIP = currentOrNull(); internalIP = currentOrNull();
} else if (qName.equalsIgnoreCase("InternalPort")) { } else if (qName.equalsIgnoreCase("InternalPort")) {
internalPort = Integer.parseInt(currentOrNull()); internalPort = Integer.parseInt(currentOrNull());
} else if (qName.equals("NatProtocol")) { } else if (equalsOrSuffix(qName, "Protocol")) {
natProtocol = NatProtocol.valueOf(currentOrNull()); natProtocol = NatProtocol.valueOf(currentOrNull());
} else if (qName.equals("PortForwardingRule")) { } else if (qName.equals("PortForwardingRule")) {
natRules.add(new PortForwardingRule(externalIP, externalPort, internalIP, internalPort, natProtocol)); 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 java.net.URI;
import javax.ws.rs.core.HttpHeaders;
import org.jclouds.http.HttpResponse; import org.jclouds.http.HttpResponse;
import org.jclouds.http.functions.BaseHandlerTest; import org.jclouds.http.functions.BaseHandlerTest;
import org.jclouds.io.Payloads; import org.jclouds.io.Payloads;
@ -55,7 +53,7 @@ public class ParseLoginResponseFromHeadersTest extends BaseHandlerTest {
@Test @Test
public void testApply() { public void testApply() {
HttpResponse response = new HttpResponse(200, "OK", Payloads.newInputStreamPayload(getClass() 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().setContentType("Content-Type: application/xml; charset=utf-8");
response.getPayload().getContentMetadata().setContentLength(307l); response.getPayload().getContentMetadata().setContentLength(307l);
@ -69,15 +67,28 @@ public class ParseLoginResponseFromHeadersTest extends BaseHandlerTest {
@Test @Test
public void testApplyBlueLock() { public void testApplyBlueLock() {
HttpResponse response = new HttpResponse(200, "OK", Payloads.newInputStreamPayload(getClass() 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().setContentType("Content-Type: application/xml; charset=utf-8");
response.getPayload().getContentMetadata().setContentLength(307l); response.getPayload().getContentMetadata().setContentLength(307l);
VCloudSession reply = parser.apply(response); 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", 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")))); 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> <version>1.0-SNAPSHOT</version>
<relativePath>../project/pom.xml</relativePath> <relativePath>../project/pom.xml</relativePath>
</parent> </parent>
<artifactId>jclouds-compute</artifactId> <artifactId>jclouds-compute</artifactId>
<name>jclouds compute core</name> <name>jclouds compute core</name>
<description>jclouds components to access compute providers</description> <description>jclouds components to access compute providers</description>
<packaging>bundle</packaging>
<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>
<dependencies> <dependencies>
<dependency> <dependency>
@ -70,4 +66,21 @@
<scope>test</scope> <scope>test</scope>
</dependency> </dependency>
</dependencies> </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> </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 [org.jclouds.compute.domain
Template TemplateBuilder ComputeMetadata NodeMetadata Hardware Template TemplateBuilder ComputeMetadata NodeMetadata Hardware
OsFamily Image] OsFamily Image]
[org.jclouds.compute.options TemplateOptions] [org.jclouds.compute.options TemplateOptions RunScriptOptions
RunScriptOptions$Builder]
[org.jclouds.compute.predicates [org.jclouds.compute.predicates
NodePredicates] NodePredicates]
[com.google.common.collect ImmutableSet]) [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 (defn suspend-node
"Suspend a node, given its id." "Suspend a node, given its id."
([id #^ComputeService compute] ([#^ComputeService compute id]
(.suspendNode compute id))) (.suspendNode compute id)))
(defn resume-nodes-matching (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 (defn resume-node
"Resume a node, given its id." "Resume a node, given its id."
([id #^ComputeService compute] ([#^ComputeService compute id]
(.resumeNode compute id))) (.resumeNode compute id)))
(defn reboot-nodes-matching (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 (defn reboot-node
"Reboot a node, given its id." "Reboot a node, given its id."
([id #^ComputeService compute] ([#^ComputeService compute id]
(.rebootNode compute id))) (.rebootNode compute id)))
(defn destroy-nodes-matching (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 (defn destroy-node
"Destroy a node, given its id." "Destroy a node, given its id."
([id #^ComputeService compute] ([#^ComputeService compute id]
(.destroyNode 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] (defmacro state-predicate [node state]
`(= (.getState ~node) `(= (.getState ~node)
(. org.jclouds.compute.domain.NodeState ~state))) (. org.jclouds.compute.domain.NodeState ~state)))

View File

@ -319,4 +319,40 @@ public interface ComputeService {
Map<? extends NodeMetadata, ExecResponse> runScriptOnNodesMatching(Predicate<NodeMetadata> filter, Map<? extends NodeMetadata, ExecResponse> runScriptOnNodesMatching(Predicate<NodeMetadata> filter,
Statement runScript, RunScriptOptions options) throws RunScriptOnNodesException; 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; package org.jclouds.compute.domain;
import java.util.Set;
import javax.annotation.Nullable;
import org.jclouds.compute.domain.internal.ComputeMetadataImpl; import org.jclouds.compute.domain.internal.ComputeMetadataImpl;
import org.jclouds.domain.ResourceMetadata; import org.jclouds.domain.ResourceMetadata;
@ -30,24 +34,23 @@ import com.google.inject.ImplementedBy;
@ImplementedBy(ComputeMetadataImpl.class) @ImplementedBy(ComputeMetadataImpl.class)
public interface ComputeMetadata extends ResourceMetadata<ComputeType> { public interface ComputeMetadata extends ResourceMetadata<ComputeType> {
/** /**
* Type of the resource, ex node, image, size * @return Type of the resource, ex node, image, size
*
*/ */
@Override @Override
public ComputeType getType(); 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 @Override
public String getProviderId(); public String getProviderId();
/** /**
* user defined name of the server. * @return user defined name of the server.
*
*/ */
@Override @Override
@Nullable
public String getName(); 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 * a node or image is region based, the id will likely include both the region and the
* provider-supplied id encoded to avoid collisions. * provider-supplied id encoded to avoid collisions.
* *
* @return unique id within your account on the provider
*/ */
public String getId(); 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.net.URI;
import java.util.Map; import java.util.Map;
import java.util.Set;
import org.jclouds.compute.domain.internal.ComputeMetadataImpl; import org.jclouds.compute.domain.internal.ComputeMetadataImpl;
import org.jclouds.domain.Location; import org.jclouds.domain.Location;
import org.jclouds.domain.ResourceMetadataBuilder; import org.jclouds.domain.ResourceMetadataBuilder;
import com.google.common.collect.ImmutableSet;
/** /**
* *
* @author Adrian Cole * @author Adrian Cole
@ -34,9 +37,9 @@ import org.jclouds.domain.ResourceMetadataBuilder;
public class ComputeMetadataBuilder extends ResourceMetadataBuilder<ComputeType> { public class ComputeMetadataBuilder extends ResourceMetadataBuilder<ComputeType> {
protected String id; protected String id;
protected ComputeType type; protected ComputeType type;
protected Set<String> tags = ImmutableSet.<String>of();
public ComputeMetadataBuilder(ComputeType type) { public ComputeMetadataBuilder(ComputeType type) {
super();
this.type = checkNotNull(type, "type"); this.type = checkNotNull(type, "type");
} }
@ -45,6 +48,11 @@ public class ComputeMetadataBuilder extends ResourceMetadataBuilder<ComputeType>
return this; 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; * set id and providerId to the same value;
*/ */
@ -79,11 +87,11 @@ public class ComputeMetadataBuilder extends ResourceMetadataBuilder<ComputeType>
} }
public ComputeMetadata build() { 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) { public static ComputeMetadataBuilder fromComputeMetadata(ComputeMetadata in) {
return new ComputeMetadataBuilder(in.getType()).id(in.getId()).location(in.getLocation()).name(in.getName()) 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.net.URI;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Set;
import org.jclouds.compute.domain.internal.HardwareImpl; import org.jclouds.compute.domain.internal.HardwareImpl;
import org.jclouds.compute.predicates.ImagePredicates; import org.jclouds.compute.predicates.ImagePredicates;
@ -88,6 +89,11 @@ public class HardwareBuilder extends ComputeMetadataBuilder {
return HardwareBuilder.class.cast(super.id(id)); return HardwareBuilder.class.cast(super.id(id));
} }
@Override
public HardwareBuilder tags(Set<String> tags) {
return HardwareBuilder.class.cast(super.tags(tags));
}
@Override @Override
public HardwareBuilder ids(String id) { public HardwareBuilder ids(String id) {
return HardwareBuilder.class.cast(super.ids(id)); return HardwareBuilder.class.cast(super.ids(id));
@ -120,14 +126,14 @@ public class HardwareBuilder extends ComputeMetadataBuilder {
@Override @Override
public Hardware build() { 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); supportsImage);
} }
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public static HardwareBuilder fromHardware(Hardware in) { public static HardwareBuilder fromHardware(Hardware in) {
return new HardwareBuilder().id(in.getId()).providerId(in.getProviderId()).location(in.getLocation()).name( 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())) List.class.cast(in.getProcessors())).ram(in.getRam()).volumes(List.class.cast(in.getVolumes()))
.supportsImage(in.supportsImage()); .supportsImage(in.supportsImage());
} }

View File

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

View File

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

View File

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

View File

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

View File

@ -25,6 +25,7 @@ import static org.jclouds.compute.util.ComputeServiceUtils.getSpace;
import java.net.URI; import java.net.URI;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Set;
import javax.annotation.Nullable; import javax.annotation.Nullable;
@ -53,9 +54,9 @@ public class HardwareImpl extends ComputeMetadataImpl implements Hardware {
private final Predicate<Image> supportsImage; private final Predicate<Image> supportsImage;
public HardwareImpl(String providerId, String name, String id, @Nullable Location location, URI uri, 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) { 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.processors = ImmutableList.copyOf(checkNotNull(processors, "processors"));
this.ram = ram; this.ram = ram;
this.volumes = ImmutableList.copyOf(checkNotNull(volumes, "volumes")); this.volumes = ImmutableList.copyOf(checkNotNull(volumes, "volumes"));
@ -106,7 +107,7 @@ public class HardwareImpl extends ComputeMetadataImpl implements Hardware {
@Override @Override
public String toString() { public String toString() {
return "[id=" + getId() + ", providerId=" + getProviderId() + ", name=" + getName() + ", processors=" 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.net.URI;
import java.util.Map; import java.util.Map;
import java.util.Set;
import javax.annotation.Nullable; import javax.annotation.Nullable;
@ -47,9 +48,9 @@ public class ImageImpl extends ComputeMetadataImpl implements Image {
private final Credentials defaultCredentials; private final Credentials defaultCredentials;
public ImageImpl(String providerId, String name, String id, Location location, URI uri, 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) { @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.operatingSystem = checkNotNull(operatingSystem, "operatingSystem");
this.version = version; this.version = version;
this.description = checkNotNull(description, "description"); this.description = checkNotNull(description, "description");
@ -102,7 +103,7 @@ public class ImageImpl extends ComputeMetadataImpl implements Image {
return "[id=" + getId() + ", name=" + getName() + ", operatingSystem=" + operatingSystem + ", description=" return "[id=" + getId() + ", name=" + getName() + ", operatingSystem=" + operatingSystem + ", description="
+ description + ", version=" + version + ", location=" + getLocation() + ", loginUser=" + description + ", version=" + version + ", location=" + getLocation() + ", loginUser="
+ ((defaultCredentials != null) ? defaultCredentials.identity : null) + ", userMetadata=" + ((defaultCredentials != null) ? defaultCredentials.identity : null) + ", userMetadata="
+ getUserMetadata() + "]"; + getUserMetadata() + ", tags=" + tags + "]";
} }
@Override @Override

View File

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

View File

@ -557,10 +557,10 @@ public class TemplateBuilderImpl implements TemplateBuilder {
} }
protected Hardware resolveSize(Ordering<Hardware> hardwareOrdering, final Iterable<? extends Image> images) { 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; Hardware hardware;
try { try {
Iterable<? extends Hardware> hardwaresThatAreCompatibleWithOurImages = filter(hardwaresl, Iterable<? extends Hardware> hardwaresThatAreCompatibleWithOurImages = filter(hardwarel,
new Predicate<Hardware>() { new Predicate<Hardware>() {
@Override @Override
public boolean apply(final Hardware hardware) { public boolean apply(final Hardware hardware) {
@ -582,7 +582,7 @@ public class TemplateBuilderImpl implements TemplateBuilder {
}); });
hardware = hardwareOrdering.max(filter(hardwaresThatAreCompatibleWithOurImages, hardwarePredicate)); hardware = hardwareOrdering.max(filter(hardwaresThatAreCompatibleWithOurImages, hardwarePredicate));
} catch (NoSuchElementException exception) { } 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); + "\n" + images);
} }
logger.debug("<< matched hardware(%s)", hardware); 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.Image;
import org.jclouds.compute.domain.NodeMetadata; import org.jclouds.compute.domain.NodeMetadata;
import org.jclouds.compute.domain.NodeMetadataBuilder; import org.jclouds.compute.domain.NodeMetadataBuilder;
import org.jclouds.compute.domain.NodeState;
import org.jclouds.compute.domain.Template; import org.jclouds.compute.domain.Template;
import org.jclouds.compute.domain.TemplateBuilder; import org.jclouds.compute.domain.TemplateBuilder;
import org.jclouds.compute.options.RunScriptOptions; 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.RunScriptOnNodeAndAddToGoodMapOrPutExceptionIntoBadMap;
import org.jclouds.compute.strategy.SuspendNodeStrategy; import org.jclouds.compute.strategy.SuspendNodeStrategy;
import org.jclouds.domain.Credentials; import org.jclouds.domain.Credentials;
import org.jclouds.domain.Credentials.Builder;
import org.jclouds.domain.Location; import org.jclouds.domain.Location;
import org.jclouds.domain.Credentials.Builder;
import org.jclouds.io.Payload; import org.jclouds.io.Payload;
import org.jclouds.logging.Logger; import org.jclouds.logging.Logger;
import org.jclouds.predicates.RetryablePredicate; import org.jclouds.predicates.RetryablePredicate;
@ -132,22 +133,25 @@ public class BaseComputeService implements ComputeService {
private final Timeouts timeouts; private final Timeouts timeouts;
private final InitAdminAccess initAdminAccess; private final InitAdminAccess initAdminAccess;
private final PersistNodeCredentials persistNodeCredentials; private final PersistNodeCredentials persistNodeCredentials;
private final RunScriptOnNode.Factory runScriptOnNodeFactory;
private final ExecutorService executor; private final ExecutorService executor;
@Inject @Inject
protected BaseComputeService(ComputeServiceContext context, Map<String, Credentials> credentialStore, protected BaseComputeService(ComputeServiceContext context, Map<String, Credentials> credentialStore,
@Memoized Supplier<Set<? extends Image>> images, @Memoized Supplier<Set<? extends Hardware>> hardwareProfiles, @Memoized Supplier<Set<? extends Image>> images,
@Memoized Supplier<Set<? extends Location>> locations, ListNodesStrategy listNodesStrategy, @Memoized Supplier<Set<? extends Hardware>> hardwareProfiles,
GetNodeMetadataStrategy getNodeMetadataStrategy, CreateNodesInGroupThenAddToSet runNodesAndAddToSetStrategy, @Memoized Supplier<Set<? extends Location>> locations, ListNodesStrategy listNodesStrategy,
RebootNodeStrategy rebootNodeStrategy, DestroyNodeStrategy destroyNodeStrategy, GetNodeMetadataStrategy getNodeMetadataStrategy,
ResumeNodeStrategy resumeNodeStrategy, SuspendNodeStrategy suspendNodeStrategy, CreateNodesInGroupThenAddToSet runNodesAndAddToSetStrategy, RebootNodeStrategy rebootNodeStrategy,
Provider<TemplateBuilder> templateBuilderProvider, Provider<TemplateOptions> templateOptionsProvider, DestroyNodeStrategy destroyNodeStrategy, ResumeNodeStrategy resumeNodeStrategy,
@Named("NODE_RUNNING") Predicate<NodeMetadata> nodeRunning, SuspendNodeStrategy suspendNodeStrategy, Provider<TemplateBuilder> templateBuilderProvider,
@Named("NODE_TERMINATED") Predicate<NodeMetadata> nodeTerminated, Provider<TemplateOptions> templateOptionsProvider,
@Named("NODE_SUSPENDED") Predicate<NodeMetadata> nodeSuspended, @Named("NODE_RUNNING") Predicate<NodeMetadata> nodeRunning,
InitializeRunScriptOnNodeOrPlaceInBadMap.Factory initScriptRunnerFactory, InitAdminAccess initAdminAccess, @Named("NODE_TERMINATED") Predicate<NodeMetadata> nodeTerminated,
PersistNodeCredentials persistNodeCredentials, Timeouts timeouts, @Named("NODE_SUSPENDED") Predicate<NodeMetadata> nodeSuspended,
@Named(Constants.PROPERTY_USER_THREADS) ExecutorService executor) { 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.context = checkNotNull(context, "context");
this.credentialStore = checkNotNull(credentialStore, "credentialStore"); this.credentialStore = checkNotNull(credentialStore, "credentialStore");
this.images = checkNotNull(images, "images"); this.images = checkNotNull(images, "images");
@ -168,6 +172,7 @@ public class BaseComputeService implements ComputeService {
this.initScriptRunnerFactory = checkNotNull(initScriptRunnerFactory, "initScriptRunnerFactory"); this.initScriptRunnerFactory = checkNotNull(initScriptRunnerFactory, "initScriptRunnerFactory");
this.timeouts = checkNotNull(timeouts, "timeouts"); this.timeouts = checkNotNull(timeouts, "timeouts");
this.initAdminAccess = checkNotNull(initAdminAccess, "initAdminAccess"); this.initAdminAccess = checkNotNull(initAdminAccess, "initAdminAccess");
this.runScriptOnNodeFactory = checkNotNull(runScriptOnNodeFactory, "runScriptOnNodeFactory");
this.persistNodeCredentials = checkNotNull(persistNodeCredentials, "persistNodeCredentials"); this.persistNodeCredentials = checkNotNull(persistNodeCredentials, "persistNodeCredentials");
this.executor = checkNotNull(executor, "executor"); this.executor = checkNotNull(executor, "executor");
} }
@ -185,7 +190,7 @@ public class BaseComputeService implements ComputeService {
*/ */
@Override @Override
public Set<? extends NodeMetadata> runNodesWithTag(String group, int count, Template template) public Set<? extends NodeMetadata> runNodesWithTag(String group, int count, Template template)
throws RunNodesException { throws RunNodesException {
return createNodesInGroup(group, count, template); return createNodesInGroup(group, count, template);
} }
@ -194,7 +199,7 @@ public class BaseComputeService implements ComputeService {
*/ */
@Override @Override
public Set<? extends NodeMetadata> runNodesWithTag(String group, int count, TemplateOptions templateOptions) public Set<? extends NodeMetadata> runNodesWithTag(String group, int count, TemplateOptions templateOptions)
throws RunNodesException { throws RunNodesException {
return createNodesInGroup(group, count, templateBuilder().any().options(templateOptions).build()); return createNodesInGroup(group, count, templateBuilder().any().options(templateOptions).build());
} }
@ -208,12 +213,12 @@ public class BaseComputeService implements ComputeService {
@Override @Override
public Set<? extends NodeMetadata> createNodesInGroup(String group, int count, Template template) public Set<? extends NodeMetadata> createNodesInGroup(String group, int count, Template template)
throws RunNodesException { throws RunNodesException {
checkNotNull(group, "group cannot be null"); checkNotNull(group, "group cannot be null");
checkNotNull(template.getLocation(), "location"); checkNotNull(template.getLocation(), "location");
logger.debug(">> running %d node%s group(%s) location(%s) image(%s) hardwareProfile(%s) options(%s)", count, 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 count > 1 ? "s" : "", group, template.getLocation().getId(), template.getImage().getId(), template
.getHardware().getId(), template.getOptions()); .getHardware().getId(), template.getOptions());
Set<NodeMetadata> goodNodes = newLinkedHashSet(); Set<NodeMetadata> goodNodes = newLinkedHashSet();
Map<NodeMetadata, Exception> badNodes = newLinkedHashMap(); Map<NodeMetadata, Exception> badNodes = newLinkedHashMap();
Multimap<NodeMetadata, CustomizationResponse> customizationResponses = LinkedHashMultimap.create(); Multimap<NodeMetadata, CustomizationResponse> customizationResponses = LinkedHashMultimap.create();
@ -222,9 +227,9 @@ public class BaseComputeService implements ComputeService {
template.getOptions().runScript(initAdminAccess.apply(template.getOptions().getRunScript())); template.getOptions().runScript(initAdminAccess.apply(template.getOptions().getRunScript()));
Map<?, Future<Void>> responses = runNodesAndAddToSetStrategy.execute(group, count, template, goodNodes, badNodes, Map<?, Future<Void>> responses = runNodesAndAddToSetStrategy.execute(group, count, template, goodNodes, badNodes,
customizationResponses); customizationResponses);
Map<?, Exception> executionExceptions = awaitCompletion(responses, executor, null, logger, "runNodesWithTag(" Map<?, Exception> executionExceptions = awaitCompletion(responses, executor, null, logger, "runNodesWithTag("
+ group + ")"); + group + ")");
Function<NodeMetadata, NodeMetadata> fn = persistNodeCredentials.always(template.getOptions().getRunScript()); Function<NodeMetadata, NodeMetadata> fn = persistNodeCredentials.always(template.getOptions().getRunScript());
badNodes = Maps2.transformKeys(badNodes, fn); badNodes = Maps2.transformKeys(badNodes, fn);
goodNodes = ImmutableSet.copyOf(Iterables.transform(goodNodes, fn)); goodNodes = ImmutableSet.copyOf(Iterables.transform(goodNodes, fn));
@ -236,7 +241,7 @@ public class BaseComputeService implements ComputeService {
@Override @Override
public Set<? extends NodeMetadata> createNodesInGroup(String group, int count, TemplateOptions templateOptions) public Set<? extends NodeMetadata> createNodesInGroup(String group, int count, TemplateOptions templateOptions)
throws RunNodesException { throws RunNodesException {
return createNodesInGroup(group, count, templateBuilder().any().options(templateOptions).build()); 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) { public Set<? extends NodeMetadata> destroyNodesMatching(Predicate<NodeMetadata> filter) {
logger.debug(">> destroying nodes matching(%s)", filter); logger.debug(">> destroying nodes matching(%s)", filter);
Set<NodeMetadata> set = newLinkedHashSet(transformParallel(nodesMatchingFilterAndNotTerminated(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 // TODO make an async interface instead of re-wrapping
@Override @Override
public Future<NodeMetadata> apply(final NodeMetadata from) { public Future<NodeMetadata> apply(final NodeMetadata from) {
return executor.submit(new Callable<NodeMetadata>() { return executor.submit(new Callable<NodeMetadata>() {
@Override @Override
public NodeMetadata call() throws Exception { public NodeMetadata call() throws Exception {
destroyNode(from.getId()); destroyNode(from.getId());
return from; return from;
} }
@Override @Override
public String toString() { public String toString() {
return "destroyNode(" + from.getId() + ")"; return "destroyNode(" + from.getId() + ")";
} }
}); });
} }
}, executor, null, logger, "destroyNodesMatching(" + filter + ")")); }, executor, null, logger, "destroyNodesMatching(" + filter + ")"));
logger.debug("<< destroyed(%d)", set.size()); logger.debug("<< destroyed(%d)", set.size());
return set; return set;
} }
@ -316,7 +321,7 @@ public class BaseComputeService implements ComputeService {
* if none found * if none found
*/ */
Iterable<? extends NodeMetadata> nodesMatchingFilterAndNotTerminatedExceptionIfNotFound( Iterable<? extends NodeMetadata> nodesMatchingFilterAndNotTerminatedExceptionIfNotFound(
Predicate<NodeMetadata> filter) { Predicate<NodeMetadata> filter) {
Iterable<? extends NodeMetadata> nodes = nodesMatchingFilterAndNotTerminated(filter); Iterable<? extends NodeMetadata> nodes = nodesMatchingFilterAndNotTerminated(filter);
if (Iterables.size(nodes) == 0) if (Iterables.size(nodes) == 0)
throw new NoSuchElementException("no nodes matched filter: " + filter); throw new NoSuchElementException("no nodes matched filter: " + filter);
@ -406,15 +411,15 @@ public class BaseComputeService implements ComputeService {
public void rebootNodesMatching(Predicate<NodeMetadata> filter) { public void rebootNodesMatching(Predicate<NodeMetadata> filter) {
logger.debug(">> rebooting nodes matching(%s)", filter); logger.debug(">> rebooting nodes matching(%s)", filter);
transformParallel(nodesMatchingFilterAndNotTerminatedExceptionIfNotFound(filter), transformParallel(nodesMatchingFilterAndNotTerminatedExceptionIfNotFound(filter),
new Function<NodeMetadata, Future<Void>>() { new Function<NodeMetadata, Future<Void>>() {
// TODO use native async // TODO use native async
@Override @Override
public Future<Void> apply(NodeMetadata from) { public Future<Void> apply(NodeMetadata from) {
rebootNode(from.getId()); rebootNode(from.getId());
return immediateFuture(null); return immediateFuture(null);
} }
}, executor, null, logger, "rebootNodesMatching(" + filter + ")"); }, executor, null, logger, "rebootNodesMatching(" + filter + ")");
logger.debug("<< rebooted"); logger.debug("<< rebooted");
} }
@ -437,15 +442,15 @@ public class BaseComputeService implements ComputeService {
public void resumeNodesMatching(Predicate<NodeMetadata> filter) { public void resumeNodesMatching(Predicate<NodeMetadata> filter) {
logger.debug(">> resuming nodes matching(%s)", filter); logger.debug(">> resuming nodes matching(%s)", filter);
transformParallel(nodesMatchingFilterAndNotTerminatedExceptionIfNotFound(filter), transformParallel(nodesMatchingFilterAndNotTerminatedExceptionIfNotFound(filter),
new Function<NodeMetadata, Future<Void>>() { new Function<NodeMetadata, Future<Void>>() {
// TODO use native async // TODO use native async
@Override @Override
public Future<Void> apply(NodeMetadata from) { public Future<Void> apply(NodeMetadata from) {
resumeNode(from.getId()); resumeNode(from.getId());
return immediateFuture(null); return immediateFuture(null);
} }
}, executor, null, logger, "resumeNodesMatching(" + filter + ")"); }, executor, null, logger, "resumeNodesMatching(" + filter + ")");
logger.debug("<< resumed"); logger.debug("<< resumed");
} }
@ -468,15 +473,15 @@ public class BaseComputeService implements ComputeService {
public void suspendNodesMatching(Predicate<NodeMetadata> filter) { public void suspendNodesMatching(Predicate<NodeMetadata> filter) {
logger.debug(">> suspending nodes matching(%s)", filter); logger.debug(">> suspending nodes matching(%s)", filter);
transformParallel(nodesMatchingFilterAndNotTerminatedExceptionIfNotFound(filter), transformParallel(nodesMatchingFilterAndNotTerminatedExceptionIfNotFound(filter),
new Function<NodeMetadata, Future<Void>>() { new Function<NodeMetadata, Future<Void>>() {
// TODO use native async // TODO use native async
@Override @Override
public Future<Void> apply(NodeMetadata from) { public Future<Void> apply(NodeMetadata from) {
suspendNode(from.getId()); suspendNode(from.getId());
return immediateFuture(null); return immediateFuture(null);
} }
}, executor, null, logger, "suspendNodesMatching(" + filter + ")"); }, executor, null, logger, "suspendNodesMatching(" + filter + ")");
logger.debug("<< suspended"); logger.debug("<< suspended");
} }
@ -485,7 +490,7 @@ public class BaseComputeService implements ComputeService {
*/ */
@Override @Override
public Map<NodeMetadata, ExecResponse> runScriptOnNodesMatching(Predicate<NodeMetadata> filter, Payload runScript) public Map<NodeMetadata, ExecResponse> runScriptOnNodesMatching(Predicate<NodeMetadata> filter, Payload runScript)
throws RunScriptOnNodesException { throws RunScriptOnNodesException {
return runScriptOnNodesMatching(filter, runScript, RunScriptOptions.NONE); return runScriptOnNodesMatching(filter, runScript, RunScriptOptions.NONE);
} }
@ -494,10 +499,10 @@ public class BaseComputeService implements ComputeService {
*/ */
@Override @Override
public Map<NodeMetadata, ExecResponse> runScriptOnNodesMatching(Predicate<NodeMetadata> filter, Payload runScript, public Map<NodeMetadata, ExecResponse> runScriptOnNodesMatching(Predicate<NodeMetadata> filter, Payload runScript,
RunScriptOptions options) throws RunScriptOnNodesException { RunScriptOptions options) throws RunScriptOnNodesException {
try { try {
return runScriptOnNodesMatching(filter, return runScriptOnNodesMatching(filter, Statements.exec(Strings2.toStringAndClose(checkNotNull(runScript,
Statements.exec(Strings2.toStringAndClose(checkNotNull(runScript, "runScript").getInput())), options); "runScript").getInput())), options);
} catch (IOException e) { } catch (IOException e) {
Throwables.propagate(e); Throwables.propagate(e);
return null; return null;
@ -509,7 +514,7 @@ public class BaseComputeService implements ComputeService {
*/ */
@Override @Override
public Map<NodeMetadata, ExecResponse> runScriptOnNodesMatching(Predicate<NodeMetadata> filter, String runScript) public Map<NodeMetadata, ExecResponse> runScriptOnNodesMatching(Predicate<NodeMetadata> filter, String runScript)
throws RunScriptOnNodesException { throws RunScriptOnNodesException {
return runScriptOnNodesMatching(filter, Statements.exec(checkNotNull(runScript, "runScript"))); return runScriptOnNodesMatching(filter, Statements.exec(checkNotNull(runScript, "runScript")));
} }
@ -518,15 +523,15 @@ public class BaseComputeService implements ComputeService {
*/ */
@Override @Override
public Map<NodeMetadata, ExecResponse> runScriptOnNodesMatching(Predicate<NodeMetadata> filter, Statement runScript) public Map<NodeMetadata, ExecResponse> runScriptOnNodesMatching(Predicate<NodeMetadata> filter, Statement runScript)
throws RunScriptOnNodesException { throws RunScriptOnNodesException {
return runScriptOnNodesMatching(filter, runScript, RunScriptOptions.NONE); return runScriptOnNodesMatching(filter, runScript, RunScriptOptions.NONE);
} }
@Override @Override
public Map<? extends NodeMetadata, ExecResponse> runScriptOnNodesMatching(Predicate<NodeMetadata> filter, 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")), return runScriptOnNodesMatching(filter, Statements.exec(checkNotNull(runScript, "runScript")),
RunScriptOptions.NONE); RunScriptOptions.NONE);
} }
/** /**
@ -534,7 +539,7 @@ public class BaseComputeService implements ComputeService {
*/ */
@Override @Override
public Map<NodeMetadata, ExecResponse> runScriptOnNodesMatching(Predicate<NodeMetadata> filter, Statement runScript, public Map<NodeMetadata, ExecResponse> runScriptOnNodesMatching(Predicate<NodeMetadata> filter, Statement runScript,
RunScriptOptions options) throws RunScriptOnNodesException { RunScriptOptions options) throws RunScriptOnNodesException {
checkNotNull(filter, "filter"); checkNotNull(filter, "filter");
checkNotNull(runScript, "runScript"); checkNotNull(runScript, "runScript");
@ -548,11 +553,11 @@ public class BaseComputeService implements ComputeService {
runScript = initAdminAccess.apply(runScript); runScript = initAdminAccess.apply(runScript);
Iterable<? extends RunScriptOnNode> scriptRunners = transformNodesIntoInitializedScriptRunners( Iterable<? extends RunScriptOnNode> scriptRunners = transformNodesIntoInitializedScriptRunners(
nodesMatchingFilterAndNotTerminatedExceptionIfNotFound(filter), runScript, options, badNodes); nodesMatchingFilterAndNotTerminatedExceptionIfNotFound(filter), runScript, options, badNodes);
if (Iterables.size(scriptRunners) > 0) { if (Iterables.size(scriptRunners) > 0) {
for (RunScriptOnNode runner : scriptRunners) { for (RunScriptOnNode runner : scriptRunners) {
responses.put(runner.getNode(), executor.submit(new RunScriptOnNodeAndAddToGoodMapOrPutExceptionIntoBadMap( responses.put(runner.getNode(), executor.submit(new RunScriptOnNodeAndAddToGoodMapOrPutExceptionIntoBadMap(
runner, goodNodes, badNodes))); runner, goodNodes, badNodes)));
} }
exceptions = awaitCompletion(responses, executor, null, logger, "runScriptOnNodesMatching(" + filter + ")"); exceptions = awaitCompletion(responses, executor, null, logger, "runScriptOnNodesMatching(" + filter + ")");
} }
@ -567,12 +572,49 @@ public class BaseComputeService implements ComputeService {
return goodNodes; 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( private Iterable<? extends RunScriptOnNode> transformNodesIntoInitializedScriptRunners(
Iterable<? extends NodeMetadata> nodes, Statement script, RunScriptOptions options, Iterable<? extends NodeMetadata> nodes, Statement script, RunScriptOptions options,
Map<NodeMetadata, Exception> badNodes) { Map<NodeMetadata, Exception> badNodes) {
return filter( return filter(transformParallel(nodes, new TransformNodesIntoInitializedScriptRunners(script, options, badNodes),
transformParallel(nodes, new TransformNodesIntoInitializedScriptRunners(script, options, badNodes), executor, null, logger, "initialize script runners"), notNull());
executor, null, logger, "initialize script runners"), notNull());
} }
private Set<? extends NodeMetadata> detailsOnAllNodes() { private Set<? extends NodeMetadata> detailsOnAllNodes() {
@ -585,13 +627,13 @@ public class BaseComputeService implements ComputeService {
} }
private final class TransformNodesIntoInitializedScriptRunners implements private final class TransformNodesIntoInitializedScriptRunners implements
Function<NodeMetadata, Future<RunScriptOnNode>> { Function<NodeMetadata, Future<RunScriptOnNode>> {
private final Map<NodeMetadata, Exception> badNodes; private final Map<NodeMetadata, Exception> badNodes;
private final Statement script; private final Statement script;
private final RunScriptOptions options; private final RunScriptOptions options;
private TransformNodesIntoInitializedScriptRunners(Statement script, RunScriptOptions options, private TransformNodesIntoInitializedScriptRunners(Statement script, RunScriptOptions options,
Map<NodeMetadata, Exception> badNodes) { Map<NodeMetadata, Exception> badNodes) {
this.badNodes = checkNotNull(badNodes, "badNodes"); this.badNodes = checkNotNull(badNodes, "badNodes");
this.script = checkNotNull(script, "script"); this.script = checkNotNull(script, "script");
this.options = checkNotNull(options, "options"); this.options = checkNotNull(options, "options");
@ -602,7 +644,7 @@ public class BaseComputeService implements ComputeService {
checkNotNull(node, "node"); checkNotNull(node, "node");
if (options.getOverridingCredentials() != null) { if (options.getOverridingCredentials() != null) {
Builder<? extends Credentials> builder = node.getCredentials() != null ? node.getCredentials().toBuilder() Builder<? extends Credentials> builder = node.getCredentials() != null ? node.getCredentials().toBuilder()
: new Credentials.Builder<Credentials>(); : new Credentials.Builder<Credentials>();
if (options.getOverridingCredentials().identity != null) if (options.getOverridingCredentials().identity != null)
builder.identity(options.getOverridingCredentials().identity); builder.identity(options.getOverridingCredentials().identity);
if (options.getOverridingCredentials().credential != null) 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.io.IOException;
import java.util.Arrays; import java.util.Arrays;
import java.util.Set;
import org.jclouds.domain.Credentials; import org.jclouds.domain.Credentials;
import org.jclouds.io.Payload; import org.jclouds.io.Payload;
@ -31,6 +32,7 @@ import org.jclouds.scriptbuilder.domain.Statements;
import org.jclouds.util.Strings2; import org.jclouds.util.Strings2;
import com.google.common.base.Throwables; import com.google.common.base.Throwables;
import com.google.common.collect.ImmutableSet;
/** /**
* Contains options supported in the {@code ComputeService#runNodesWithTag} operation. <h2> * 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()); to.blockOnPort(this.getPort(), this.getSeconds());
if (this.isIncludeMetadata()) if (this.isIncludeMetadata())
to.withMetadata(); to.withMetadata();
if (this.getTags().size() > 0)
to.tags(getTags());
if (!this.shouldBlockUntilRunning()) if (!this.shouldBlockUntilRunning())
to.blockUntilRunning(false); to.blockUntilRunning(false);
if (!this.shouldBlockOnComplete()) if (!this.shouldBlockOnComplete())
@ -276,6 +280,8 @@ public class TemplateOptions extends RunScriptOptions implements Cloneable {
protected Statement script; protected Statement script;
protected Set<String> tags = ImmutableSet.of();
protected String privateKey; protected String privateKey;
protected String publicKey; protected String publicKey;
@ -292,6 +298,10 @@ public class TemplateOptions extends RunScriptOptions implements Cloneable {
return script; return script;
} }
public Set<String> getTags() {
return tags;
}
public String getPrivateKey() { public String getPrivateKey() {
return privateKey; return privateKey;
} }
@ -350,7 +360,7 @@ public class TemplateOptions extends RunScriptOptions implements Cloneable {
*/ */
public TemplateOptions installPrivateKey(String privateKey) { public TemplateOptions installPrivateKey(String privateKey) {
checkArgument(checkNotNull(privateKey, "privateKey").startsWith("-----BEGIN RSA PRIVATE KEY-----"), 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; this.privateKey = privateKey;
return this; 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. * Opens the set of ports to public access.
*/ */
@ -461,6 +479,14 @@ public class TemplateOptions extends RunScriptOptions implements Cloneable {
return options.inboundPorts(ports); 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 * @see TemplateOptions#blockUntilRunning
*/ */
@ -556,9 +582,9 @@ public class TemplateOptions extends RunScriptOptions implements Cloneable {
@Override @Override
public String toString() { public String toString() {
return "[inboundPorts=" + Arrays.toString(inboundPorts) + ", privateKey=" + (privateKey != null) + ", publicKey=" return "[inboundPorts=" + Arrays.toString(inboundPorts) + ", privateKey=" + (privateKey != null) + ", publicKey="
+ (publicKey != null) + ", runScript=" + (script != null) + ", blockUntilRunning=" + blockUntilRunning + (publicKey != null) + ", runScript=" + (script != null) + ", blockUntilRunning=" + blockUntilRunning
+ ", blockOnComplete=" + blockOnComplete + ", port:seconds=" + port + ":" + seconds + ", blockOnComplete=" + blockOnComplete + ", port:seconds=" + port + ":" + seconds
+ ", metadata/details: " + includeMetadata + "]"; + ", metadata/details: " + includeMetadata + "]";
} }
public TemplateOptions blockUntilRunning(boolean blockUntilRunning) { public TemplateOptions blockUntilRunning(boolean blockUntilRunning) {

View File

@ -57,7 +57,7 @@ public interface ComputeServiceConstants {
public static class ReferenceData { public static class ReferenceData {
@Inject(optional = true) @Inject(optional = true)
@Named(PROPERTY_OS_VERSION_MAP_JSON) @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 @Singleton

View File

@ -45,8 +45,9 @@ import org.jclouds.rest.ResourceNotFoundException;
import com.google.common.base.Supplier; import com.google.common.base.Supplier;
import com.google.common.base.Throwables; import com.google.common.base.Throwables;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet; 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() + ""; String id = idProvider.get() + "";
builder.ids(id); builder.ids(id);
builder.name(name); builder.name(name);
builder.tags(template.getOptions().getTags());
builder.group(group); builder.group(group);
builder.location(location.get()); builder.location(location.get());
builder.imageId(template.getImage().getId()); builder.imageId(template.getImage().getId());
@ -110,18 +112,19 @@ public class StubComputeServiceAdapter implements JCloudsNativeComputeServiceAda
@Override @Override
public Iterable<Image> listImages() { public Iterable<Image> listImages() {
Credentials defaultCredentials = new Credentials("root", null); 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; int id = 1;
for (boolean is64Bit : new boolean[] { true, false }) for (boolean is64Bit : new boolean[] { true, false })
for (Entry<OsFamily, Map<String, String>> osVersions : this.osToVersionMap.entrySet()) { 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); String desc = String.format("stub %s %s", osVersions.getKey(), is64Bit);
images.add(new ImageBuilder().ids(id++ + "").name(osVersions.getKey().name()).location(location.get()) images.add(new ImageBuilder().ids(id++ + "").name(osVersions.getKey().name()).location(location.get())
.operatingSystem(new OperatingSystem(osVersions.getKey(), desc, version, null, desc, is64Bit)) .operatingSystem(new OperatingSystem(osVersions.getKey(), desc, version, null, desc, is64Bit))
.description(desc).defaultCredentials(defaultCredentials).build()); .description(desc).defaultCredentials(defaultCredentials).build());
} }
} }
return images; return images.build();
} }
@Override @Override

View File

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

View File

@ -20,10 +20,19 @@
(ns org.jclouds.compute2-test (ns org.jclouds.compute2-test
(:use [org.jclouds.compute2] :reload-all) (:use [org.jclouds.compute2] :reload-all)
(:use clojure.test) (:use clojure.test)
(:require [org.jclouds.ssh-test :as ssh-test])
(:import (:import
org.jclouds.compute.domain.OsFamily org.jclouds.compute.domain.OsFamily
clojure.contrib.condition.Condition)) 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] (defmacro with-private-vars [[ns fns] & tests]
"Refers private fns from ns and runs tests in context. From users mailing "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 (deftest os-families-test
(is (some #{"centos"} (map str (os-families))))) (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 (defn clean-stub-fixture
"This should allow basic tests to easily be run with another service." "This should allow basic tests to easily be run with another service."
[compute-service] [compute-service]
(fn [f] (fn [f]
(doseq [node (nodes compute-service)] (doseq [node (nodes compute-service)]
(destroy-node (.getId node))) (destroy-node compute-service (.getId node)))
(f))) (f)))
(def *compute* (compute-service "stub" "" ""))
(use-fixtures :each (clean-stub-fixture *compute*)) (use-fixtures :each (clean-stub-fixture *compute*))
(deftest compute-service?-test (deftest compute-service?-test
@ -54,34 +63,64 @@ list, Alan Dipert and MeikelBrandmeyer."
(is (compute-service? *compute*)) (is (compute-service? *compute*))
(is (compute-service? (compute-service (compute-context *compute*))))) (is (compute-service? (compute-service (compute-context *compute*)))))
(defn in-group [group] #(= (.getGroup %) group)) (defn in-group? [group] #(= (.getGroup %) group))
(deftest nodes-test (deftest nodes-test
(is (empty? (nodes *compute*)))
(is (create-node *compute* "fred" (build-template *compute* {} ))) (is (create-node *compute* "fred" (build-template *compute* {} )))
(is (= 1 (count (nodes *compute*))))
(is (= 1 (count (nodes-in-group *compute* "fred")))) (is (= 1 (count (nodes-in-group *compute* "fred"))))
;; pass in a function that selects node metadata based on NodeMetadata field ;; 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 ;; or make your query inline
(is (= 1 (count (nodes-with-details-matching *compute* #(= (.getGroup %) "fred"))))) (is (= 1 (count (nodes-with-details-matching *compute* #(= (.getGroup %) "fred")))))
;; or get real fancy, and use the underlying Predicate object jclouds uses ;; or get real fancy, and use the underlying Predicate object jclouds uses
(is (= 1 (count (nodes-with-details-matching *compute* (is (= 1 (count (nodes-with-details-matching *compute*
(reify com.google.common.base.Predicate (reify com.google.common.base.Predicate
(apply [this input] (= (.getGroup input) "fred"))))))) (apply [this input] (= (.getGroup input) "fred")))))))
(is (= 0 (count (nodes-with-details-matching *compute* (in-group "othergroup"))))) (is (= 0 (count (nodes-with-details-matching *compute* (in-group? "othergroup")))))
(suspend-nodes-matching *compute* (in-group "fred")) (suspend-nodes-matching *compute* (in-group? "fred"))
(is (suspended? (first (nodes-with-details-matching *compute* (in-group "fred"))))) (is (suspended? (first (nodes-with-details-matching *compute* (in-group? "fred")))))
(resume-nodes-matching *compute* (in-group "fred")) (resume-nodes-matching *compute* (in-group? "fred"))
(is (running? (first (nodes-in-group *compute* "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 (running? (first (nodes-in-group *compute* "fred"))))
(is (create-nodes *compute* "fred" 2 (build-template *compute* {} ))) (is (create-nodes *compute* "fred" 2 (build-template *compute* {} )))
(is (= 3 (count (nodes-in-group *compute* "fred")))) (is (= 3 (count (nodes-in-group *compute* "fred"))))
(is (= "fred" (group (first (nodes *compute*))))) (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"))))) (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 (deftest build-template-test
(let [service (compute-service "stub" "user" "password")] (let [service (compute-service "stub" "user" "password")]
(testing "nullary" (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] (defn instantiate [impl-class & args]
(let [constructor (first (let [constructor (first
(filter (filter
@ -73,7 +83,12 @@
(^org.jclouds.ssh.SshClient (^org.jclouds.ssh.SshClient
create create
[_ ^IPSocket socket ^String username ^bytes password-or-key] [_ ^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 (deftype Module
[factory binder] [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.filter;
import static com.google.common.collect.Sets.newTreeSet; import static com.google.common.collect.Sets.newTreeSet;
import static org.jclouds.compute.ComputeTestUtils.buildScript; 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.blockOnComplete;
import static org.jclouds.compute.options.TemplateOptions.Builder.overrideCredentialsWith; import static org.jclouds.compute.options.TemplateOptions.Builder.overrideCredentialsWith;
import static org.jclouds.compute.predicates.NodePredicates.TERMINATED; import static org.jclouds.compute.predicates.NodePredicates.TERMINATED;
@ -44,12 +45,12 @@ import java.io.FileNotFoundException;
import java.io.IOException; import java.io.IOException;
import java.util.Collection; import java.util.Collection;
import java.util.Map; import java.util.Map;
import java.util.Map.Entry;
import java.util.NoSuchElementException; import java.util.NoSuchElementException;
import java.util.Properties; import java.util.Properties;
import java.util.Set; import java.util.Set;
import java.util.SortedSet; import java.util.SortedSet;
import java.util.TreeSet; import java.util.TreeSet;
import java.util.Map.Entry;
import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException; import java.util.concurrent.TimeoutException;
@ -160,8 +161,8 @@ public abstract class BaseComputeServiceLiveTest {
if (context != null) if (context != null)
context.close(); context.close();
Properties props = setupProperties(); Properties props = setupProperties();
context = new ComputeServiceContextFactory(setupRestProperties()).createContext(provider, context = new ComputeServiceContextFactory(setupRestProperties()).createContext(provider, ImmutableSet.of(
ImmutableSet.of(new Log4JLoggingModule(), getSshModule()), props); new Log4JLoggingModule(), getSshModule()), props);
client = context.getComputeService(); client = context.getComputeService();
} }
@ -182,7 +183,7 @@ public abstract class BaseComputeServiceLiveTest {
ComputeServiceContext context = null; ComputeServiceContext context = null;
try { try {
context = new ComputeServiceContextFactory(setupRestProperties()).createContext(provider, "MOMMA", "MIA", context = new ComputeServiceContextFactory(setupRestProperties()).createContext(provider, "MOMMA", "MIA",
ImmutableSet.<Module> of(new Log4JLoggingModule())); ImmutableSet.<Module> of(new Log4JLoggingModule()));
context.getComputeService().listNodes(); context.getComputeService().listNodes();
} catch (AuthorizationException e) { } catch (AuthorizationException e) {
throw e; throw e;
@ -207,7 +208,7 @@ public abstract class BaseComputeServiceLiveTest {
@Test(enabled = true, expectedExceptions = NoSuchElementException.class) @Test(enabled = true, expectedExceptions = NoSuchElementException.class)
public void testCorrectExceptionRunningNodesNotFound() throws Exception { public void testCorrectExceptionRunningNodesNotFound() throws Exception {
client.runScriptOnNodesMatching(runningInGroup("zebras-are-awesome"), buildScript(new OperatingSystem.Builder() 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 // 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(); OperatingSystem os = get(nodes, 0).getOperatingSystem();
try { try {
Map<? extends NodeMetadata, ExecResponse> responses = runScriptWithCreds(group, os, new Credentials( 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; assert false : "shouldn't pass with a bad password\n" + responses;
} catch (RunScriptOnNodesException e) { } catch (RunScriptOnNodesException e) {
assert getRootCause(e).getMessage().contains("Auth fail") : e; assert getRootCause(e).getMessage().contains("Auth fail") : e;
} }
for (Entry<? extends NodeMetadata, ExecResponse> response : client.runScriptOnNodesMatching( for (Entry<? extends NodeMetadata, ExecResponse> response : client.runScriptOnNodesMatching(
runningInGroup(group), Statements.exec("echo hello"), runningInGroup(group), Statements.exec("echo hello"),
overrideCredentialsWith(good).wrapInInitScript(false).runAsRoot(false)).entrySet()) overrideCredentialsWith(good).wrapInInitScript(false).runAsRoot(false)).entrySet())
assert response.getValue().getOutput().trim().equals("hello") : response.getKey() + ": " 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); runScriptWithCreds(group, os, good);
@ -298,7 +304,8 @@ public abstract class BaseComputeServiceLiveTest {
// template.getOptions().installPrivateKey(keyPair.get("private")).authorizePublicKey(keyPair.get("public")) // template.getOptions().installPrivateKey(keyPair.get("private")).authorizePublicKey(keyPair.get("public"))
// .runScript(buildScript(template.getImage().getOperatingSystem())); // .runScript(buildScript(template.getImage().getOperatingSystem()));
template.getOptions().runScript( template.getOptions().runScript(
Statements.newStatementList(AdminAccess.standard(), buildScript(template.getImage().getOperatingSystem()))); Statements.newStatementList(AdminAccess.standard(),
buildScript(template.getImage().getOperatingSystem())));
} }
protected void checkImageIdMatchesTemplate(NodeMetadata node) { protected void checkImageIdMatchesTemplate(NodeMetadata node) {
@ -309,8 +316,8 @@ public abstract class BaseComputeServiceLiveTest {
protected void checkOsMatchesTemplate(NodeMetadata node) { protected void checkOsMatchesTemplate(NodeMetadata node) {
if (node.getOperatingSystem() != null) if (node.getOperatingSystem() != null)
assert node.getOperatingSystem().getFamily().equals(template.getImage().getOperatingSystem().getFamily()) : String assert node.getOperatingSystem().getFamily().equals(template.getImage().getOperatingSystem().getFamily()) : String
.format("expecting family %s but got %s", template.getImage().getOperatingSystem().getFamily(), .format("expecting family %s but got %s", template.getImage().getOperatingSystem().getFamily(), node
node.getOperatingSystem()); .getOperatingSystem());
} }
void assertLocationSameOrChild(Location test, Location expected) { 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, protected Map<? extends NodeMetadata, ExecResponse> runScriptWithCreds(final String group, OperatingSystem os,
Credentials creds) throws RunScriptOnNodesException { Credentials creds) throws RunScriptOnNodesException {
try { try {
return client.runScriptOnNodesMatching(runningInGroup(group), buildScript(os), overrideCredentialsWith(creds) return client.runScriptOnNodesMatching(runningInGroup(group), buildScript(os), overrideCredentialsWith(creds)
.nameTask("runScriptWithCreds")); .nameTask("runScriptWithCreds"));
} catch (SshException e) { } catch (SshException e) {
throw e; throw e;
} }
@ -375,16 +382,16 @@ public abstract class BaseComputeServiceLiveTest {
@Test(enabled = true, dependsOnMethods = "testCreateAnotherNodeWithANewContextToEnsureSharedMemIsntRequired") @Test(enabled = true, dependsOnMethods = "testCreateAnotherNodeWithANewContextToEnsureSharedMemIsntRequired")
public void testGet() throws Exception { public void testGet() throws Exception {
Map<String, ? extends NodeMetadata> metadataMap = newLinkedHashMap(uniqueIndex( Map<String, ? extends NodeMetadata> metadataMap = newLinkedHashMap(uniqueIndex(filter(client
filter(client.listNodesDetailsMatching(all()), and(inGroup(group), not(TERMINATED))), .listNodesDetailsMatching(all()), and(inGroup(group), not(TERMINATED))),
new Function<NodeMetadata, String>() { new Function<NodeMetadata, String>() {
@Override @Override
public String apply(NodeMetadata from) { public String apply(NodeMetadata from) {
return from.getId(); return from.getId();
} }
})); }));
for (NodeMetadata node : nodes) { for (NodeMetadata node : nodes) {
metadataMap.remove(node.getId()); metadataMap.remove(node.getId());
NodeMetadata metadata = client.getNodeMetadata(node.getId()); NodeMetadata metadata = client.getNodeMetadata(node.getId());
@ -403,7 +410,7 @@ public abstract class BaseComputeServiceLiveTest {
protected void assertNodeZero(Collection<? extends NodeMetadata> metadataSet) { protected void assertNodeZero(Collection<? extends NodeMetadata> metadataSet) {
assert metadataSet.size() == 0 : String.format("nodes left in set: [%s] which didn't match set: [%s]", 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") @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)) template = client.templateBuilder().options(blockOnComplete(false).blockOnPort(8080, 600).inboundPorts(22, 8080))
.build(); .build();
// note this is a dependency on the template resolution // note this is a dependency on the template resolution
template.getOptions().runScript( template.getOptions().runScript(
RunScriptData.createScriptInstallAndStartJBoss(keyPair.get("public"), template.getImage() RunScriptData.createScriptInstallAndStartJBoss(keyPair.get("public"), template.getImage()
.getOperatingSystem())); .getOperatingSystem()));
try { try {
NodeMetadata node = getOnlyElement(client.createNodesInGroup(group, 1, template)); NodeMetadata node = getOnlyElement(client.createNodesInGroup(group, 1, template));
@ -530,26 +537,26 @@ public abstract class BaseComputeServiceLiveTest {
assert location != location.getParent() : location; assert location != location.getParent() : location;
assert location.getScope() != null : location; assert location.getScope() != null : location;
switch (location.getScope()) { switch (location.getScope()) {
case PROVIDER: case PROVIDER:
assertProvider(location); assertProvider(location);
break; break;
case REGION: case REGION:
assertProvider(location.getParent()); assertProvider(location.getParent());
break; break;
case ZONE: case ZONE:
Location provider = location.getParent().getParent(); Location provider = location.getParent().getParent();
// zone can be a direct descendant of provider // zone can be a direct descendant of provider
if (provider == null) if (provider == null)
provider = location.getParent(); provider = location.getParent();
assertProvider(provider); assertProvider(provider);
break; break;
case HOST: case HOST:
Location provider2 = location.getParent().getParent().getParent(); Location provider2 = location.getParent().getParent().getParent();
// zone can be a direct descendant of provider // zone can be a direct descendant of provider
if (provider2 == null) if (provider2 == null)
provider2 = location.getParent().getParent(); provider2 = location.getParent().getParent();
assertProvider(provider2); assertProvider(provider2);
break; break;
} }
} }
} }
@ -582,10 +589,10 @@ public abstract class BaseComputeServiceLiveTest {
public void testListSizes() throws Exception { public void testListSizes() throws Exception {
for (Hardware hardware : client.listHardwareProfiles()) { for (Hardware hardware : client.listHardwareProfiles()) {
assert hardware.getProviderId() != null; assert hardware.getProviderId() != null : hardware;
assert getCores(hardware) > 0; assert getCores(hardware) > 0 : hardware;
assert hardware.getVolumes().size() >= 0; assert hardware.getVolumes().size() >= 0 : hardware;
assert hardware.getRam() > 0; assert hardware.getRam() > 0 : hardware;
assertEquals(hardware.getType(), ComputeType.HARDWARE); assertEquals(hardware.getType(), ComputeType.HARDWARE);
} }
} }
@ -637,7 +644,7 @@ public abstract class BaseComputeServiceLiveTest {
assertEquals(hello.getOutput().trim(), "hello"); assertEquals(hello.getOutput().trim(), "hello");
ExecResponse exec = ssh.exec("java -version"); ExecResponse exec = ssh.exec("java -version");
assert exec.getError().indexOf("1.6") != -1 || exec.getOutput().indexOf("1.6") != -1 : exec + "\n" 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 { } finally {
if (ssh != null) if (ssh != null)
ssh.disconnect(); ssh.disconnect();

View File

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

View File

@ -144,11 +144,16 @@ public class StubComputeServiceIntegrationTest extends BaseComputeServiceLiveTes
runScriptAndService(client1, 1); runScriptAndService(client1, 1);
expect(factory.create(new IPSocket("144.175.1.2", 22), new Credentials("root", "password2"))).andReturn( 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( expect(factory.create(new IPSocket("144.175.1.2", 22), new Credentials("root", "romeo"))).andThrow(
new SshException("Auth fail")); 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(); client2.connect();
expect(client2.exec("echo hello\n")).andReturn(new ExecResponse("hello\n", "", 0)); expect(client2.exec("echo hello\n")).andReturn(new ExecResponse("hello\n", "", 0));
client2.disconnect(); client2.disconnect();

View File

@ -2,7 +2,7 @@
<!-- <!--
Copyright (C) 2010 Cloud Conscious, LLC. Copyright (C) 2011 Cloud Conscious, LLC.
<info@cloudconscious.com> <info@cloudconscious.com>
==================================================================== ====================================================================
@ -30,7 +30,7 @@
</parent> </parent>
<artifactId>jclouds-core</artifactId> <artifactId>jclouds-core</artifactId>
<name>jclouds Components Core</name> <name>jclouds Components Core</name>
<packaging>jar</packaging> <packaging>bundle</packaging>
<description>Core components to access jclouds services</description> <description>Core components to access jclouds services</description>
<scm> <scm>
@ -105,7 +105,7 @@
<dependency> <dependency>
<groupId>com.google.code.gson</groupId> <groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId> <artifactId>gson</artifactId>
<version>1.6</version> <version>1.7.1</version>
</dependency> </dependency>
<dependency> <dependency>
<groupId>com.google.guava</groupId> <groupId>com.google.guava</groupId>
@ -119,6 +119,43 @@
</dependency> </dependency>
</dependencies> </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> <profiles>
<profile> <profile>
<id>distribution</id> <id>distribution</id>

View File

@ -23,11 +23,12 @@ import static com.google.common.base.Preconditions.checkNotNull;
import java.io.IOException; import java.io.IOException;
/** /**
* The gson project use package to control access to their objects. However, * The gson project use package to control access to their objects. However, this prevents us from
* this prevents us from doing valid work, like controling the json emitted on a * doing valid work, like controling the json emitted on a per-object basis. This is here to afford
* per-object basis. This is here to afford us to do this. * us to do this.
* *
* @author Adrian Cole * @author Adrian Cole
* @see <a href="http://code.google.com/p/google-gson/issues/detail?id=326"/>
*/ */
public final class JsonLiteral extends JsonElement { public final class JsonLiteral extends JsonElement {
private final CharSequence literal; 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"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
* You may obtain a copy of the License at * You may obtain a copy of the License at
@ -14,8 +12,8 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
* ====================================================================
*/ */
package com.google.gson; package com.google.gson;
import com.google.gson.stream.JsonReader; import com.google.gson.stream.JsonReader;
@ -104,7 +102,8 @@ final class Streams {
if (serializeNulls) { if (serializeNulls) {
writer.nullValue(); 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 ) { } else if (element instanceof JsonLiteral ) {
writer.value(JsonLiteral.class.cast(element)); writer.value(JsonLiteral.class.cast(element));
//END JCLOUDS PATCH //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"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
* You may obtain a copy of the License at * 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 * Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, * distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
* ====================================================================
*/ */
package com.google.gson.stream; package com.google.gson.stream;
import java.io.Closeable; import java.io.Closeable;
@ -344,7 +342,7 @@ public final class JsonWriter implements Closeable {
return this; return this;
} }
//BEGIN JCLOUDS PATCH //BEGIN JCLOUDS PATCH
// * @see <a href="http://code.google.com/p/google-gson/issues/detail?id=326"/>
/** /**
* Writes {@code value} literally * Writes {@code value} literally
* *
@ -356,7 +354,6 @@ public final class JsonWriter implements Closeable {
return this; return this;
} }
//END JCLOUDS PATCH //END JCLOUDS PATCH
/** /**
* Encodes {@code value}. * 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 * As String is final, using a different marker to imply this is a json object
* *
* @author Adrian Cole * @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 { public class JsonBall implements java.io.Serializable, Comparable<String>, CharSequence {

View File

@ -16,13 +16,14 @@
* limitations under the License. * 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.Inject;
import javax.inject.Singleton; import javax.inject.Singleton;
import org.jclouds.http.HttpResponse; import org.jclouds.http.HttpResponse;
import org.jclouds.ibmdev.domain.Instance;
import com.google.common.base.Function; import com.google.common.base.Function;
import com.google.common.collect.Iterables; import com.google.common.collect.Iterables;
@ -31,16 +32,20 @@ import com.google.common.collect.Iterables;
* @author Adrian Cole * @author Adrian Cole
*/ */
@Singleton @Singleton
public class GetFirstInstanceInList implements Function<HttpResponse, Instance> { public class UnwrapOnlyJsonValueInSet<T> implements Function<HttpResponse, T> {
private ParseInstancesFromJson listParser;
private final UnwrapOnlyJsonValue<Set<T>> json;
@Inject @Inject
public GetFirstInstanceInList(ParseInstancesFromJson mapper) { UnwrapOnlyJsonValueInSet(UnwrapOnlyJsonValue<Set<T>> json) {
this.listParser = mapper; this.json = json;
} }
@Override @Override
public Instance apply(HttpResponse from) { public T apply(HttpResponse arg0) {
return Iterables.getOnlyElement(listParser.apply(from)); 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. * 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.Inject;
import javax.inject.Singleton;
import org.jclouds.http.HttpResponse; import org.jclouds.collect.InputSupplierMap;
import org.jclouds.http.functions.ParseJson;
import org.jclouds.ibmdev.domain.Image;
import com.google.common.base.Function; import com.google.common.annotations.Beta;
import com.google.common.io.InputSupplier;
/** /**
*
* @author Adrian Cole * @author Adrian Cole
*/ */
@Singleton @Beta
public class ParseImageFromJson implements Function<HttpResponse, Image> { public class CopyInputStreamInputSupplierMap extends InputSupplierMap<String, InputStream> {
private final ParseJson<Image> json;
@Inject @Inject
ParseImageFromJson(ParseJson<Image> json) { public CopyInputStreamInputSupplierMap(Map<String, InputSupplier<InputStream>> toMap,
this.json = json; CopyInputStreamIntoSupplier putFunction) {
super(toMap, putFunction);
} }
@Override public CopyInputStreamInputSupplierMap(Map<String, InputSupplier<InputStream>> toMap) {
public Image apply(HttpResponse arg0) { super(toMap, new CopyInputStreamIntoSupplier());
Image input = json.apply(arg0);
ParseUtils.CLEAN_IMAGE.apply(input);
return input;
} }
} }

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.List;
import java.util.Map; import java.util.Map;
import java.util.Properties; import java.util.Properties;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.inject.Inject; import javax.inject.Inject;
import javax.inject.Singleton; import javax.inject.Singleton;
@ -36,12 +38,11 @@ import org.jclouds.json.internal.EnumTypeAdapterThatReturnsFromValue;
import org.jclouds.json.internal.GsonWrapper; import org.jclouds.json.internal.GsonWrapper;
import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableMap.Builder;
import com.google.common.collect.Maps; import com.google.common.collect.Maps;
import com.google.common.collect.ImmutableMap.Builder;
import com.google.common.primitives.Bytes; import com.google.common.primitives.Bytes;
import com.google.gson.Gson; import com.google.gson.Gson;
import com.google.gson.GsonBuilder; import com.google.gson.GsonBuilder;
import com.google.gson.JcloudsGsonPackageAccessor;
import com.google.gson.JsonDeserializationContext; import com.google.gson.JsonDeserializationContext;
import com.google.gson.JsonDeserializer; import com.google.gson.JsonDeserializer;
import com.google.gson.JsonElement; import com.google.gson.JsonElement;
@ -50,7 +51,7 @@ import com.google.gson.JsonParseException;
import com.google.gson.JsonPrimitive; import com.google.gson.JsonPrimitive;
import com.google.gson.JsonSerializationContext; import com.google.gson.JsonSerializationContext;
import com.google.gson.JsonSerializer; import com.google.gson.JsonSerializer;
import com.google.gson.MapTypeAdapter; import com.google.gson.ObjectMapTypeAdapter;
import com.google.gson.reflect.TypeToken; import com.google.gson.reflect.TypeToken;
import com.google.inject.AbstractModule; import com.google.inject.AbstractModule;
import com.google.inject.ImplementedBy; import com.google.inject.ImplementedBy;
@ -68,12 +69,12 @@ public class GsonModule extends AbstractModule {
@Provides @Provides
@Singleton @Singleton
Gson provideGson(JsonBallAdapter jsonAdapter, DateAdapter adapter, ByteListAdapter byteListAdapter, Gson provideGson(JsonBallAdapter jsonAdapter, DateAdapter adapter, ByteListAdapter byteListAdapter,
ByteArrayAdapter byteArrayAdapter, SerializePropertiesDefaults propertiesAdapter, JsonAdapterBindings bindings) ByteArrayAdapter byteArrayAdapter, SerializePropertiesDefaults propertiesAdapter,
throws ClassNotFoundException, Exception { JsonAdapterBindings bindings) throws ClassNotFoundException, Exception {
GsonBuilder builder = new GsonBuilder(); GsonBuilder builder = new GsonBuilder();
JcloudsGsonPackageAccessor.registerTypeHierarchyAdapter(builder, Enum.class, Logger.getLogger("com.google.gson.ParameterizedTypeHandlerMap").setLevel(Level.OFF);
new EnumTypeAdapterThatReturnsFromValue()); builder.registerTypeHierarchyAdapter(Enum.class, new EnumTypeAdapterThatReturnsFromValue());
JcloudsGsonPackageAccessor.registerTypeHierarchyAdapter(builder, Map.class, new MapTypeAdapter()); builder.registerTypeHierarchyAdapter(Map.class, new ObjectMapTypeAdapter());
builder.registerTypeAdapter(JsonBall.class, jsonAdapter); builder.registerTypeAdapter(JsonBall.class, jsonAdapter);
builder.registerTypeAdapter(Date.class, adapter); builder.registerTypeAdapter(Date.class, adapter);
builder.registerTypeAdapter(Properties.class, propertiesAdapter); builder.registerTypeAdapter(Properties.class, propertiesAdapter);
@ -86,6 +87,7 @@ public class GsonModule extends AbstractModule {
return builder.create(); return builder.create();
} }
// http://code.google.com/p/google-gson/issues/detail?id=326
@ImplementedBy(JsonBallAdapterImpl.class) @ImplementedBy(JsonBallAdapterImpl.class)
public static interface JsonBallAdapter extends JsonSerializer<JsonBall>, JsonDeserializer<JsonBall> { 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) public JsonBall deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context)
throws JsonParseException { throws JsonParseException {
return new JsonBall(json.toString()); return new JsonBall(json.toString());
} }
@ -125,7 +127,7 @@ public class GsonModule extends AbstractModule {
@Override @Override
public List<Byte> deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) public List<Byte> deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context)
throws JsonParseException { throws JsonParseException {
return Bytes.asList(CryptoStreams.hex(json.getAsString())); return Bytes.asList(CryptoStreams.hex(json.getAsString()));
} }
@ -141,7 +143,7 @@ public class GsonModule extends AbstractModule {
@Override @Override
public byte[] deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) public byte[] deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context)
throws JsonParseException { throws JsonParseException {
return CryptoStreams.hex(json.getAsString()); return CryptoStreams.hex(json.getAsString());
} }
@ -165,7 +167,7 @@ public class GsonModule extends AbstractModule {
} }
public Date deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) public Date deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context)
throws JsonParseException { throws JsonParseException {
String toParse = json.getAsJsonPrimitive().getAsString(); String toParse = json.getAsJsonPrimitive().getAsString();
try { try {
return dateService.iso8601DateParse(toParse); return dateService.iso8601DateParse(toParse);
@ -212,7 +214,7 @@ public class GsonModule extends AbstractModule {
} }
public Date deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) public Date deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context)
throws JsonParseException { throws JsonParseException {
String toParse = json.getAsJsonPrimitive().getAsString(); String toParse = json.getAsJsonPrimitive().getAsString();
Date toReturn = dateService.cDateParse(toParse); Date toReturn = dateService.cDateParse(toParse);
return toReturn; return toReturn;
@ -228,7 +230,7 @@ public class GsonModule extends AbstractModule {
} }
public Date deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) public Date deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context)
throws JsonParseException { throws JsonParseException {
long toParse = json.getAsJsonPrimitive().getAsLong(); long toParse = json.getAsJsonPrimitive().getAsLong();
if (toParse == -1) if (toParse == -1)
return null; 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. * 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 * @author Adrian Cole
*/ */
public enum JsonObjectAsMap implements Function<JsonObject, Map<String, JsonElement>> { 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.common.collect.Maps;
import com.google.gson.JsonElement; import com.google.gson.JsonElement;
import com.google.gson.JsonPrimitive; 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 * This is a class that helps the default {@link MapTypeAdapter} make a sane object graph when the
* value is set to {@code Object} * value is set to {@code Object}
* * http://code.google.com/p/google-gson/issues/detail?id=325
* @author Adrian Cole * @author Adrian Cole
*/ */
public enum ParseObjectFromElement implements Function<JsonElement, Object> { 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; package org.jclouds.providers;
import java.net.URI; import java.net.URI;
import java.util.Set;
import javax.annotation.Nullable;
/** /**
* The ProviderMetadata interface allows jclouds to provide a plugin framework * The ProviderMetadata interface allows jclouds to provide a plugin framework for gathering cloud
* for gathering cloud provider metadata. * provider metadata.
* *
* @author Jeremy Whitlock <jwhitlock@apache.org> * @author Jeremy Whitlock <jwhitlock@apache.org>
*/ */
@ -30,40 +33,64 @@ public interface ProviderMetadata {
public static final String BLOBSTORE_TYPE = "blobstore"; public static final String BLOBSTORE_TYPE = "blobstore";
public static final String COMPUTE_TYPE = "compute"; 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
* @return the provider's unique identifier */
*/ public String getId();
public String getId();
/** /**
* Returns the provider type. *
* * @return the provider's type
* @return the provider's type */
*/ public String getType();
public String getType();
/** /**
* Returns the name of the provider. *
* * @return the name (display name) of the provider
* @return the name (display name) of the provider */
*/ public String getName();
public String getName();
/** /**
* Returns the URI to the provider's homepage. *
* * @return the name (display name) of an identity on this provider (ex. user, email, account,
* @return the url for the provider's homepage * apikey)
*/ */
public URI getHomepage(); public String getIdentityName();
/** /**
* Returns the URI to the provider's console. *
* * @return the name (display name) of a credential on this provider, or null if there is none
* @return the url for the provider's console * (ex. password, secret, rsaKey)
*/ */
public URI getConsole(); @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 { public class Providers {
/** /**
* Returns the providers located on the classpath via * Returns the providers located on the classpath via {@link java.util.ServiceLoader}.
* {@link java.util.ServiceLoader}.
* *
* @return all available providers loaded from classpath via ServiceLoader * @return all available providers loaded from classpath via ServiceLoader
*/ */
@ -59,10 +58,9 @@ public class Providers {
* @return the provider with the given id * @return the provider with the given id
* *
* @throws NoSuchElementException * @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) public static ProviderMetadata withId(String id) throws NoSuchElementException {
throws NoSuchElementException {
return find(all(), ProviderPredicates.id(id)); return find(all(), ProviderPredicates.id(id));
} }
@ -86,6 +84,36 @@ public class Providers {
return filter(all(), ProviderPredicates.type(ProviderMetadata.COMPUTE_TYPE)); 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. * 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 static com.google.common.base.Preconditions.checkNotNull;
import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.util.Map; import java.util.Map;
import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentHashMap;
@ -29,9 +28,9 @@ import javax.annotation.Resource;
import javax.inject.Inject; import javax.inject.Inject;
import javax.inject.Singleton; import javax.inject.Singleton;
import org.jclouds.collect.InputSupplierMap;
import org.jclouds.collect.TransformingMap; import org.jclouds.collect.TransformingMap;
import org.jclouds.domain.Credentials; import org.jclouds.domain.Credentials;
import org.jclouds.io.CopyInputStreamInputSupplierMap;
import org.jclouds.json.Json; import org.jclouds.json.Json;
import org.jclouds.logging.Logger; import org.jclouds.logging.Logger;
import org.jclouds.rest.ConfiguresCredentialStore; import org.jclouds.rest.ConfiguresCredentialStore;
@ -39,8 +38,6 @@ import org.jclouds.util.Strings2;
import com.google.common.annotations.Beta; import com.google.common.annotations.Beta;
import com.google.common.base.Function; 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.common.io.InputSupplier;
import com.google.inject.AbstractModule; import com.google.inject.AbstractModule;
import com.google.inject.Provides; 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 @Singleton
public static class CredentialsFromJsonInputStream implements Function<InputStream, Credentials> { public static class CredentialsFromJsonInputStream implements Function<InputStream, Credentials> {
@Resource @Resource

View File

@ -82,6 +82,7 @@ import org.jclouds.http.functions.ReturnInputStream;
import org.jclouds.http.functions.ReturnStringIf2xx; import org.jclouds.http.functions.ReturnStringIf2xx;
import org.jclouds.http.functions.ReturnTrueIf2xx; import org.jclouds.http.functions.ReturnTrueIf2xx;
import org.jclouds.http.functions.UnwrapOnlyJsonValue; import org.jclouds.http.functions.UnwrapOnlyJsonValue;
import org.jclouds.http.functions.UnwrapOnlyJsonValueInSet;
import org.jclouds.http.functions.UnwrapOnlyNestedJsonValue; import org.jclouds.http.functions.UnwrapOnlyNestedJsonValue;
import org.jclouds.http.functions.UnwrapOnlyNestedJsonValueInSet; import org.jclouds.http.functions.UnwrapOnlyNestedJsonValueInSet;
import org.jclouds.http.functions.ParseSax.HandlerWithResult; import org.jclouds.http.functions.ParseSax.HandlerWithResult;
@ -743,34 +744,7 @@ public class RestAnnotationProcessor<T> {
|| TypeLiteral.get(method.getGenericReturnType()).equals(futureHttpResponseLiteral)) { || TypeLiteral.get(method.getGenericReturnType()).equals(futureHttpResponseLiteral)) {
return Key.get((Class) IdentityFunction.class); return Key.get((Class) IdentityFunction.class);
} else if (getAcceptHeadersOrNull(method).contains(MediaType.APPLICATION_JSON)) { } else if (getAcceptHeadersOrNull(method).contains(MediaType.APPLICATION_JSON)) {
Type returnVal; return getJsonParserKeyForMethod(method);
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);
} else if (method.getReturnType().equals(String.class) } else if (method.getReturnType().equals(String.class)
|| TypeLiteral.get(method.getGenericReturnType()).equals(futureStringLiteral)) { || TypeLiteral.get(method.getGenericReturnType()).equals(futureStringLiteral)) {
return Key.get(ReturnStringIf2xx.class); return Key.get(ReturnStringIf2xx.class);
@ -784,6 +758,49 @@ public class RestAnnotationProcessor<T> {
return Key.get(annotation.value()); 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) { public static Class<? extends HandlerWithResult<?>> getSaxResponseParserClassOrNull(Method method) {
XMLResponseParser annotation = method.getAnnotation(XMLResponseParser.class); XMLResponseParser annotation = method.getAnnotation(XMLResponseParser.class);
if (annotation != null) { 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.propertiesbuilder=org.jclouds.cloudsigma.CloudSigmaZurichPropertiesBuilder
cloudsigma-zrh.contextbuilder=org.jclouds.cloudsigma.CloudSigmaContextBuilder cloudsigma-zrh.contextbuilder=org.jclouds.cloudsigma.CloudSigmaContextBuilder
ibmdev.propertiesbuilder=org.jclouds.ibmdev.IBMDeveloperCloudPropertiesBuilder ibm-smartcloud.propertiesbuilder=org.jclouds.ibm.smartcloud.IBMSmartCloudPropertiesBuilder
ibmdev.contextbuilder=org.jclouds.ibmdev.IBMDeveloperCloudContextBuilder ibm-smartcloud.contextbuilder=org.jclouds.ibm.smartcloud.IBMSmartCloudContextBuilder
stub.contextbuilder=org.jclouds.compute.stub.StubComputeServiceContextBuilder stub.contextbuilder=org.jclouds.compute.stub.StubComputeServiceContextBuilder
# example of where to change your endpoint # example of where to change your endpoint

View File

@ -20,18 +20,24 @@ package org.jclouds.json;
import static org.testng.Assert.assertEquals; 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.HttpResponse;
import org.jclouds.http.functions.UnwrapOnlyNestedJsonValue; import org.jclouds.io.Payload;
import org.jclouds.io.Payloads; import org.jclouds.io.Payloads;
import org.jclouds.json.config.GsonModule; import org.jclouds.json.config.GsonModule;
import org.jclouds.rest.internal.RestAnnotationProcessor;
import org.testng.annotations.Test; import org.testng.annotations.Test;
import com.google.common.base.Function; import com.google.common.base.Function;
import com.google.common.base.Throwables;
import com.google.inject.Guice; import com.google.inject.Guice;
import com.google.inject.Injector; 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> { 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 @Test
public void test() { public void test() {
T expects = expected(); T expects = expected();
Function<HttpResponse, T> parser = parser(injector());
Function<HttpResponse, T> parser = getParser(getInjector()); T response = parser.apply(new HttpResponse(200, "ok", payload()));
T response = parser.apply(new HttpResponse(200, "ok", Payloads.newInputStreamPayload(getClass()
.getResourceAsStream(resource()))));
compare(expects, response); compare(expects, response);
} }
protected Payload payload() {
return Payloads.newInputStreamPayload(getClass().getResourceAsStream(resource()));
}
public void compare(T expects, T response) { public void compare(T expects, T response) {
assertEquals(response.toString(), expects.toString()); assertEquals(response.toString(), expects.toString());
} }
protected Injector getInjector() { protected Injector injector() {
return Guice.createInjector(new GsonModule() { return Guice.createInjector(new GsonModule() {
@Override @Override
@ -67,15 +92,9 @@ public abstract class BaseParserTest<T, G> {
} }
@SuppressWarnings("unchecked") protected String resource() {
protected Function<HttpResponse, T> getParser(Injector i) { throw new IllegalStateException("please define resource such as \"/testaddresses.json\"");
return (Function<HttpResponse, T>) i.getInstance(Key.get(TypeLiteral.get(
Types.newParameterizedType(UnwrapOnlyNestedJsonValue.class, type())).getType()));
} }
public abstract Class<G> type();
public abstract String resource();
public abstract T expected(); public abstract T expected();
} }

View File

@ -22,15 +22,7 @@ import static org.testng.Assert.assertEquals;
import java.util.Set; 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.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> { 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) { public void compare(Set<T> expects, Set<T> response) {
assertEquals(ImmutableSortedSet.copyOf(response).toString(), ImmutableSortedSet.copyOf(expects).toString()); assertEquals(ImmutableSortedSet.copyOf(response).toString(), ImmutableSortedSet.copyOf(expects).toString());
} }

View File

@ -37,6 +37,52 @@ import com.google.inject.TypeLiteral;
public class JsonTest { public class JsonTest {
private Json json = Guice.createInjector(new GsonModule()).getInstance(Json.class); 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 class EnumInside {
private static enum Test { private static enum Test {
FOO, BAR; FOO, BAR;
@ -66,7 +112,7 @@ public class JsonTest {
map.put("map", ImmutableMap.of("key", "value")); map.put("map", ImmutableMap.of("key", "value"));
map.put("list", ImmutableList.of("key", "value")); map.put("list", ImmutableList.of("key", "value"));
assertEquals(json.toJson(map), 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>>() { Map<String, Object> map2 = json.fromJson(json.toJson(map), new TypeLiteral<Map<String, Object>>() {
}.getType()); }.getType());
assertEquals(map2, map); assertEquals(map2, map);
@ -121,12 +167,12 @@ public class JsonTest {
public void testDeserializeEnumWithParser() { public void testDeserializeEnumWithParser() {
assertEquals(json.fromJson("{enumValue : \"FOO\"}", EnumInsideWithParser.class).enumValue, assertEquals(json.fromJson("{enumValue : \"FOO\"}", EnumInsideWithParser.class).enumValue,
EnumInsideWithParser.Test.FOO); EnumInsideWithParser.Test.FOO);
} }
public void testDeserializeEnumWithParserAndBadValue() { public void testDeserializeEnumWithParserAndBadValue() {
assertEquals(json.fromJson("{enumValue : \"sd\"}", EnumInsideWithParser.class).enumValue, 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; 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> * @author Jeremy Whitlock <jwhitlock@apache.org>
*/ */
public class JcloudsTestBlobStoreProviderMetadata implements ProviderMetadata { public class JcloudsTestBlobStoreProviderMetadata extends BaseProviderMetadata {
/** /**
* {@ see org.jclouds.types.ProviderMetadata#getId()} * {@inheritDoc}
*/ */
@Override @Override
public String getId() { public String getId() {
@ -36,7 +36,7 @@ public class JcloudsTestBlobStoreProviderMetadata implements ProviderMetadata {
} }
/** /**
* {@ see org.jclouds.types.ProviderMetadata#getType()} * {@inheritDoc}
*/ */
@Override @Override
public String getType() { public String getType() {
@ -44,7 +44,7 @@ public class JcloudsTestBlobStoreProviderMetadata implements ProviderMetadata {
} }
/** /**
* {@ see org.jclouds.types.ProviderMetadata#getName()} * {@inheritDoc}
*/ */
@Override @Override
public String getName() { 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 @Override
public URI getHomepage() { public URI getHomepage() {
@ -60,11 +76,19 @@ public class JcloudsTestBlobStoreProviderMetadata implements ProviderMetadata {
} }
/** /**
* {@ see org.jclouds.types.ProviderMetadata#getConsole()} * {@inheritDoc}
*/ */
@Override @Override
public URI getConsole() { public URI getConsole() {
return URI.create("http://jclouds.org/console"); 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; 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> * @author Jeremy Whitlock <jwhitlock@apache.org>
*/ */
public class JcloudsTestComputeProviderMetadata implements ProviderMetadata { public class JcloudsTestComputeProviderMetadata extends BaseProviderMetadata {
/** /**
* {@ see org.jclouds.types.ProviderMetadata#getId()} * {@ see org.jclouds.types.ProviderMetadata#getId()}
@ -51,6 +51,22 @@ public class JcloudsTestComputeProviderMetadata implements ProviderMetadata {
return "Test Compute Provider"; return "Test Compute Provider";
} }
/**
* {@inheritDoc}
*/
@Override
public String getCredentialName() {
return "user";
}
/**
* {@inheritDoc}
*/
@Override
public String getIdentityName() {
return "password";
}
/** /**
* {@ see org.jclouds.types.ProviderMetadata#getHomepage()} * {@ see org.jclouds.types.ProviderMetadata#getHomepage()}
*/ */
@ -67,4 +83,12 @@ public class JcloudsTestComputeProviderMetadata implements ProviderMetadata {
return URI.create("http://jclouds.org/console"); 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" ) @Test( groups = "unit" )
public class ProvidersTest { public class ProvidersTest {
private final ProviderMetadata testBlobstoreProvider = new JcloudsTestBlobStoreProviderMetadata();
private final ProviderMetadata testComputeProvider = new JcloudsTestComputeProviderMetadata();
@Test @Test
public void testWithId() { public void testWithId() {
ProviderMetadata providerMetadata; ProviderMetadata providerMetadata;
@ -45,9 +48,9 @@ public class ProvidersTest {
; // Expected ; // Expected
} }
providerMetadata = Providers.withId("test-blobstore-provider"); providerMetadata = Providers.withId(testBlobstoreProvider.getId());
assertEquals("Test Blobstore Provider", providerMetadata.getName()); assertEquals(testBlobstoreProvider, providerMetadata);
} }
@Test @Test
@ -55,21 +58,13 @@ public class ProvidersTest {
Iterable<ProviderMetadata> providersMetadata = Providers.ofType(ProviderMetadata.BLOBSTORE_TYPE); Iterable<ProviderMetadata> providersMetadata = Providers.ofType(ProviderMetadata.BLOBSTORE_TYPE);
for (ProviderMetadata providerMetadata : providersMetadata) { for (ProviderMetadata providerMetadata : providersMetadata) {
assertEquals("Test Blobstore Provider", providerMetadata.getName()); assertEquals(testBlobstoreProvider, providerMetadata);
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());
} }
providersMetadata = Providers.ofType(ProviderMetadata.COMPUTE_TYPE); providersMetadata = Providers.ofType(ProviderMetadata.COMPUTE_TYPE);
for (ProviderMetadata providerMetadata : providersMetadata) { for (ProviderMetadata providerMetadata : providersMetadata) {
assertEquals("Test Compute Provider", providerMetadata.getName()); assertEquals(testComputeProvider, providerMetadata);
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());
} }
providersMetadata = Providers.ofType("fake-type"); providersMetadata = Providers.ofType("fake-type");
@ -83,16 +78,9 @@ public class ProvidersTest {
for (ProviderMetadata providerMetadata : providersMetadata) { for (ProviderMetadata providerMetadata : providersMetadata) {
if (providerMetadata.getName().equals("Test Blobstore Provider")) { if (providerMetadata.getName().equals("Test Blobstore Provider")) {
assertEquals("test-blobstore-provider", providerMetadata.getId()); assertEquals(testBlobstoreProvider, providerMetadata);
assertEquals(ProviderMetadata.BLOBSTORE_TYPE, providerMetadata.getType());
assertEquals("http://jclouds.org", providerMetadata.getHomepage().toString());
assertEquals("http://jclouds.org/console", providerMetadata.getConsole().toString());
} else { } else {
assertEquals("Test Compute Provider", providerMetadata.getName()); assertEquals(testComputeProvider, providerMetadata);
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());
} }
} }
} }

View File

@ -28,10 +28,10 @@ import java.util.concurrent.ConcurrentHashMap;
import org.jclouds.crypto.PemsTest; import org.jclouds.crypto.PemsTest;
import org.jclouds.domain.Credentials; import org.jclouds.domain.Credentials;
import org.jclouds.io.CopyInputStreamInputSupplierMap;
import org.jclouds.json.Json; import org.jclouds.json.Json;
import org.jclouds.json.config.GsonModule; import org.jclouds.json.config.GsonModule;
import org.jclouds.rest.config.CredentialStoreModule; import org.jclouds.rest.config.CredentialStoreModule;
import org.jclouds.rest.config.CredentialStoreModule.CopyInputStreamInputSupplierMap;
import org.jclouds.util.Strings2; import org.jclouds.util.Strings2;
import org.testng.annotations.DataProvider; import org.testng.annotations.DataProvider;
import org.testng.annotations.Test; import org.testng.annotations.Test;
@ -46,7 +46,7 @@ import com.google.inject.TypeLiteral;
* *
* @author Adrian Cole * @author Adrian Cole
*/ */
@Test(groups = "unit", sequential = true) @Test(groups = "unit", singleThreaded = true)
public class CredentialStoreModuleTest { public class CredentialStoreModuleTest {
Json json = createInjector().getInstance(Json.class); 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.ReturnStringIf2xx;
import org.jclouds.http.functions.ReturnTrueIf2xx; import org.jclouds.http.functions.ReturnTrueIf2xx;
import org.jclouds.http.functions.UnwrapOnlyJsonValue; import org.jclouds.http.functions.UnwrapOnlyJsonValue;
import org.jclouds.http.functions.UnwrapOnlyJsonValueInSet;
import org.jclouds.http.functions.UnwrapOnlyNestedJsonValue; import org.jclouds.http.functions.UnwrapOnlyNestedJsonValue;
import org.jclouds.http.functions.UnwrapOnlyNestedJsonValueInSet; import org.jclouds.http.functions.UnwrapOnlyNestedJsonValueInSet;
import org.jclouds.http.internal.PayloadEnclosingImpl; import org.jclouds.http.internal.PayloadEnclosingImpl;
@ -834,6 +835,12 @@ public class RestAnnotationProcessorTest extends BaseRestClientTest {
@Consumes(MediaType.APPLICATION_JSON) @Consumes(MediaType.APPLICATION_JSON)
ListenableFuture<Long> testUnwrapDepth2Long(); ListenableFuture<Long> testUnwrapDepth2Long();
@GET
@Path("/")
@Unwrap(depth = 2, edgeCollection = Set.class)
@Consumes(MediaType.APPLICATION_JSON)
ListenableFuture<String> testUnwrapDepth2Set();
@GET @GET
@Path("/") @Path("/")
@Unwrap(depth = 3, edgeCollection = Set.class) @Unwrap(depth = 3, edgeCollection = Set.class)
@ -1033,6 +1040,23 @@ public class RestAnnotationProcessorTest extends BaseRestClientTest {
.<String> of()); .<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") @SuppressWarnings("unchecked")
public void testUnwrapDepth2Long() throws SecurityException, NoSuchMethodException, IOException { public void testUnwrapDepth2Long() throws SecurityException, NoSuchMethodException, IOException {
Method method = TestPut.class.getMethod("testUnwrapDepth2Long"); 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"); Licensed under the Apache License, Version 2.0 (the "License");
@ -32,7 +32,7 @@
<groupId>org.jclouds.driver</groupId> <groupId>org.jclouds.driver</groupId>
<artifactId>jclouds-apachehc</artifactId> <artifactId>jclouds-apachehc</artifactId>
<name>jclouds Apache Http Components Client</name> <name>jclouds Apache Http Components Client</name>
<packaging>jar</packaging> <packaging>bundle</packaging>
<description>Apache HttpComponents client</description> <description>Apache HttpComponents client</description>
<!-- bootstrapping: need to fetch the project POM --> <!-- bootstrapping: need to fetch the project POM -->
@ -72,4 +72,20 @@
</dependency> </dependency>
</dependencies> </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> </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"); Licensed under the Apache License, Version 2.0 (the "License");
@ -33,6 +33,7 @@
<artifactId>jclouds-bouncycastle</artifactId> <artifactId>jclouds-bouncycastle</artifactId>
<name>jclouds bouncycastle EncryptionService Module</name> <name>jclouds bouncycastle EncryptionService Module</name>
<description>jclouds bouncycastle EncryptionService Module</description> <description>jclouds bouncycastle EncryptionService Module</description>
<packaging>bundle</packaging>
<!-- bootstrapping: need to fetch the project POM --> <!-- bootstrapping: need to fetch the project POM -->
<repositories> <repositories>
@ -65,4 +66,21 @@
<scope>compile</scope> <scope>compile</scope>
</dependency> </dependency>
</dependencies> </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> </project>

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