Merge commit '6d187ed9baaad1e00dbe65b36ea2989c951a5a28', ssh client patch is reverted due to massive changes in code

Conflicts:
	drivers/jsch/src/main/java/org/jclouds/ssh/jsch/JschSshClient.java
This commit is contained in:
Dmitri Babaev 2011-06-03 03:50:47 +04:00
commit e1f0cdcfa5
280 changed files with 6415 additions and 1346 deletions

View File

@ -32,7 +32,8 @@ our dev version is 1.0-SNAPSHOT
our compute api supports: aws-ec2, gogrid, cloudservers-us, stub (in-memory), deltacloud, our compute api supports: aws-ec2, gogrid, cloudservers-us, stub (in-memory), deltacloud,
cloudservers-uk, vcloud (generic), ec2 (generic), byon, nova, cloudservers-uk, vcloud (generic), ec2 (generic), byon, nova,
trmk-ecloud, trmk-vcloudexpress, eucalyptus (generic), trmk-ecloud, trmk-vcloudexpress, eucalyptus (generic),
cloudsigma-zrh, elasticstack(generic), bluelock-vclouddirector, cloudsigma-zrh, elasticstack(generic), bluelock-vcloud-vcenterprise,
bluelock-vcloud-zone01, stratogen-vcloud-mycloud, rimuhosting,
slicehost, eucalyptus-partnercloud-ec2, elastichosts-lon-p (Peer 1), slicehost, eucalyptus-partnercloud-ec2, elastichosts-lon-p (Peer 1),
elastichosts-sat-p (Peer 1), elastichosts-lon-b (BlueSquare), elastichosts-sat-p (Peer 1), elastichosts-lon-b (BlueSquare),
openhosting-east1, serverlove-z1-man, skalicloud-sdg-my openhosting-east1, serverlove-z1-man, skalicloud-sdg-my
@ -54,7 +55,7 @@ our loadbalancer api supports: cloudloadbalancers-us
* note * the pom dependency org.jclouds/jclouds-allloadbalancer gives you access to * note * the pom dependency org.jclouds/jclouds-allloadbalancer gives you access to
to all of these providers to all of these providers
we also have support for: ibmdev, mezeo, nirvanix, boxdotnet, rimuhosting, openstack nova, we also have support for: ibmdev, mezeo, nirvanix, boxdotnet, openstack nova,
azurequeue, simpledb, cloudstack as well as a async-http-client azurequeue, simpledb, cloudstack as well as a async-http-client
driver in the sandbox driver in the sandbox

View File

@ -49,6 +49,11 @@
<artifactId>aws-ec2</artifactId> <artifactId>aws-ec2</artifactId>
<version>${project.version}</version> <version>${project.version}</version>
</dependency> </dependency>
<dependency>
<groupId>org.jclouds.provider</groupId>
<artifactId>rimuhosting</artifactId>
<version>${project.version}</version>
</dependency>
<dependency> <dependency>
<groupId>org.jclouds.api</groupId> <groupId>org.jclouds.api</groupId>
<artifactId>nova</artifactId> <artifactId>nova</artifactId>
@ -104,6 +109,21 @@
<artifactId>bluelock-vcdirector</artifactId> <artifactId>bluelock-vcdirector</artifactId>
<version>${project.version}</version> <version>${project.version}</version>
</dependency> </dependency>
<dependency>
<groupId>org.jclouds.provider</groupId>
<artifactId>bluelock-vcloud-vcenterprise</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.jclouds.provider</groupId>
<artifactId>bluelock-vcloud-zone01</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.jclouds.provider</groupId>
<artifactId>stratogen-vcloud-mycloud</artifactId>
<version>${project.version}</version>
</dependency>
<dependency> <dependency>
<groupId>org.jclouds.provider</groupId> <groupId>org.jclouds.provider</groupId>
<artifactId>gogrid</artifactId> <artifactId>gogrid</artifactId>

View File

@ -42,6 +42,7 @@ import org.jclouds.atmos.functions.AtmosObjectName;
import org.jclouds.atmos.functions.ParseDirectoryListFromContentAndHeaders; import org.jclouds.atmos.functions.ParseDirectoryListFromContentAndHeaders;
import org.jclouds.atmos.functions.ParseObjectFromHeadersAndHttpContent; import org.jclouds.atmos.functions.ParseObjectFromHeadersAndHttpContent;
import org.jclouds.atmos.functions.ParseSystemMetadataFromHeaders; import org.jclouds.atmos.functions.ParseSystemMetadataFromHeaders;
import org.jclouds.atmos.functions.ParseUserMetadataFromHeaders;
import org.jclouds.atmos.functions.ReturnEndpointIfAlreadyExists; import org.jclouds.atmos.functions.ReturnEndpointIfAlreadyExists;
import org.jclouds.atmos.options.ListOptions; import org.jclouds.atmos.options.ListOptions;
import org.jclouds.blobstore.functions.ThrowContainerNotFoundOn404; import org.jclouds.blobstore.functions.ThrowContainerNotFoundOn404;
@ -164,7 +165,7 @@ public interface AtmosAsyncClient {
* @see AtmosClient#getUserMetadata * @see AtmosClient#getUserMetadata
*/ */
@HEAD @HEAD
@ResponseParser(ParseSystemMetadataFromHeaders.class) @ResponseParser(ParseUserMetadataFromHeaders.class)
@ExceptionParser(ReturnNullOnNotFoundOr404.class) @ExceptionParser(ReturnNullOnNotFoundOr404.class)
@Path("/{path}") @Path("/{path}")
@QueryParams(keys = "metadata/user") @QueryParams(keys = "metadata/user")

View File

@ -0,0 +1,101 @@
;
;
; 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.
; ====================================================================
;
(ns
#^{:author "Juegen Hoetzel, juergen@archlinux.org"
:doc "A clojure binding for the jclouds AWS security group interface."}
org.jclouds.ec2.security-group2
(:require (org.jclouds [compute2 :as compute])
[org.jclouds.ec2.ebs :as ebs])
(:import org.jclouds.ec2.domain.IpProtocol
org.jclouds.ec2.domain.SecurityGroup
org.jclouds.ec2.services.SecurityGroupClient))
(defn #^SecurityGroupClient
sg-service
"Returns the SecurityGroup Client associated with the specified compute service."
[compute]
(-> compute .getContext .getProviderSpecificContext .getApi .getSecurityGroupServices))
(defn create-group
"Creates a new security group.
e.g. (create-group compute \"Database Server\" \"Description for group\" :region :us-west-1)"
[compute name & {:keys [description region]}]
(.createSecurityGroupInRegion (sg-service compute) (ebs/get-region region) name (or description name)))
(defn delete-group
"Deletes a security group.
e.g. (delete-group compute \"Database Server\" :region :us-west-1)"
[compute name & {:keys [region]}]
(.deleteSecurityGroupInRegion (sg-service compute) (ebs/get-region region) name))
(defn groups
"Returns a map of GroupName -> org.jclouds.ec2.domain.SecurityGroup instances.
e.g. (groups compute :region :us-east-1)"
[compute & {:keys [region]}]
(into {} (for [#^SecurityGroup group (.describeSecurityGroupsInRegion (sg-service compute)
(ebs/get-region region)
(into-array String '()))]
[(.getName group) group])))
(defn get-protocol [v]
"Coerce argument to a IP Protocol."
(cond
(instance? IpProtocol v) v
(keyword? v) (if-let [p (get {:tcp IpProtocol/TCP
:udp IpProtocol/UDP
:icmp IpProtocol/ICMP}
v)]
p
(throw (IllegalArgumentException.
(str "Can't obtain IP protocol from " v " (valid :tcp, :udp and :icmp)"))))
(nil? v) IpProtocol/TCP
:else (throw (IllegalArgumentException.
(str "Can't obtain IP protocol from argument of type " (type v))))))
(defn authorize
"Adds permissions to a security group.
e.g. (authorize compute \"jclouds#webserver#us-east-1\" 80 :ip-range \"0.0.0.0/0\")
(authorize compute \"jclouds#webserver#us-east-1\" [1000,2000] :protocol :udp)"
[compute group-name port & {:keys [protocol ip-range region]}]
(let [group ((groups compute :region region) group-name)
[from-port to-port] (if (number? port) [port port] port)]
(if group
(.authorizeSecurityGroupIngressInRegion
(sg-service compute) (ebs/get-region region) (.getName group) (get-protocol protocol) from-port to-port (or ip-range "0.0.0.0/0"))
(throw (IllegalArgumentException.
(str "Can't find security group for name " group-name))))))
(defn revoke
"Revokes permissions from a security group.
e.g. (revoke compute 80 \"jclouds#webserver#us-east-1\" :protocol :tcp 80 80 :ip-range \"0.0.0.0/0\")"
[compute group-name port & {:keys [protocol ip-range region]}]
(let [group ((groups compute :region region) group-name)
[from-port to-port] (if (number? port) [port port] port)]
(if group
(.revokeSecurityGroupIngressInRegion
(sg-service compute) (ebs/get-region region) (.getName group) (get-protocol protocol) from-port to-port (or ip-range "0.0.0.0/0"))
(throw (IllegalArgumentException.
(str "Can't find security group for name " group-name))))))

View File

@ -209,13 +209,23 @@ public class EC2HardwareBuilder extends HardwareBuilder {
/** /**
* @see InstanceType#M1_SMALL * @see InstanceType#M1_SMALL
*/ */
public static EC2HardwareBuilder m1_small() { public static EC2HardwareBuilder m1_small32() {
return new EC2HardwareBuilder(InstanceType.M1_SMALL).ram(1740).processors( return new EC2HardwareBuilder(InstanceType.M1_SMALL).ram(1740).processors(
ImmutableList.of(new Processor(1.0, 1.0))).volumes( ImmutableList.of(new Processor(1.0, 1.0))).volumes(
ImmutableList.<Volume> of(new VolumeImpl(10.0f, "/dev/sda1", true, false), new VolumeImpl(150.0f, ImmutableList.<Volume> of(new VolumeImpl(10.0f, "/dev/sda1", true, false), new VolumeImpl(150.0f,
"/dev/sda2", false, false))).is64Bit(false); "/dev/sda2", false, false))).is64Bit(false);
} }
/**
* @see InstanceType#M1_SMALL
*/
public static EC2HardwareBuilder m1_small() {
return new EC2HardwareBuilder(InstanceType.M1_SMALL).ram(1740).processors(
ImmutableList.of(new Processor(1.0, 1.0))).volumes(
ImmutableList.<Volume> of(new VolumeImpl(10.0f, "/dev/sda1", true, false), new VolumeImpl(150.0f,
"/dev/sda2", false, false)));
}
/** /**
* @see InstanceType#T1_MICRO * @see InstanceType#T1_MICRO
*/ */

View File

@ -509,6 +509,6 @@ public class EC2TemplateOptions extends TemplateOptions implements Cloneable {
@Override @Override
public String toString() { public String toString() {
return "[groupIds=" + groupIds + ", keyPair=" + keyPair + ", noKeyPair=" + noKeyPair + ", userData=" return "[groupIds=" + groupIds + ", keyPair=" + keyPair + ", noKeyPair=" + noKeyPair + ", userData="
+ Arrays.toString(userData) + ", blockDeviceMappings=" + blockDeviceMappings + "]"; + Arrays.toString(userData) + ", blockDeviceMappings=" + blockDeviceMappings.build() + "]";
} }
} }

View File

@ -18,7 +18,6 @@
*/ */
package org.jclouds.ec2.compute.suppliers; package org.jclouds.ec2.compute.suppliers;
import static org.jclouds.compute.predicates.ImagePredicates.any;
import static org.jclouds.ec2.compute.domain.EC2HardwareBuilder.c1_medium; import static org.jclouds.ec2.compute.domain.EC2HardwareBuilder.c1_medium;
import static org.jclouds.ec2.compute.domain.EC2HardwareBuilder.c1_xlarge; import static org.jclouds.ec2.compute.domain.EC2HardwareBuilder.c1_xlarge;
import static org.jclouds.ec2.compute.domain.EC2HardwareBuilder.m1_large; import static org.jclouds.ec2.compute.domain.EC2HardwareBuilder.m1_large;
@ -43,7 +42,7 @@ public class EC2HardwareSupplier implements Supplier<Set<? extends Hardware>> {
@Override @Override
public Set<? extends Hardware> get() { public Set<? extends Hardware> get() {
return ImmutableSet.<Hardware> of(m1_small().supportsImage(any()).build(), c1_medium().build(), c1_xlarge() return ImmutableSet.<Hardware> of(m1_small().build(), c1_medium().build(), c1_xlarge()
.build(), m1_large().build(), m1_xlarge().build()); .build(), m1_large().build(), m1_xlarge().build());
} }
} }

View File

@ -26,6 +26,7 @@ import java.util.Set;
import org.jclouds.compute.BaseComputeServiceLiveTest; import org.jclouds.compute.BaseComputeServiceLiveTest;
import org.jclouds.compute.domain.NodeMetadata; import org.jclouds.compute.domain.NodeMetadata;
import org.jclouds.compute.domain.OsFamily;
import org.jclouds.compute.domain.Template; import org.jclouds.compute.domain.Template;
import org.jclouds.compute.options.TemplateOptions; import org.jclouds.compute.options.TemplateOptions;
import org.jclouds.compute.predicates.NodePredicates; import org.jclouds.compute.predicates.NodePredicates;
@ -160,11 +161,15 @@ public class EC2ComputeServiceLiveTest extends BaseComputeServiceLiveTest {
String group = this.group + "e"; String group = this.group + "e";
int volumeSize = 8; int volumeSize = 8;
final Template template = context.getComputeService().templateBuilder().hardwareId(InstanceType.M1_SMALL)
.osFamily(OsFamily.UBUNTU).osVersionMatches("10.04").imageDescriptionMatches(".*ebs.*").build();
Location zone = Iterables.find(context.getComputeService().listAssignableLocations(), new Predicate<Location>() { Location zone = Iterables.find(context.getComputeService().listAssignableLocations(), new Predicate<Location>() {
@Override @Override
public boolean apply(Location arg0) { public boolean apply(Location arg0) {
return arg0.getScope() == LocationScope.ZONE; return arg0.getScope() == LocationScope.ZONE
&& arg0.getParent().getId().equals(template.getLocation().getId());
} }
}); });
@ -174,9 +179,6 @@ public class EC2ComputeServiceLiveTest extends BaseComputeServiceLiveTest {
Snapshot snapshot = ebsClient.createSnapshotInRegion(volume.getRegion(), volume.getId()); Snapshot snapshot = ebsClient.createSnapshotInRegion(volume.getRegion(), volume.getId());
ebsClient.deleteVolumeInRegion(volume.getRegion(), volume.getId()); ebsClient.deleteVolumeInRegion(volume.getRegion(), volume.getId());
Template template = context.getComputeService().templateBuilder().locationId(volume.getRegion()).hardwareId(
InstanceType.M1_SMALL).imageDescriptionMatches(".*ebs.*").build();
template.getOptions().as(EC2TemplateOptions.class)// template.getOptions().as(EC2TemplateOptions.class)//
// .unmapDeviceNamed("/dev/foo) // .unmapDeviceNamed("/dev/foo)
.mapEphemeralDeviceToDeviceName("/dev/sdm", "ephemeral0")// .mapEphemeralDeviceToDeviceName("/dev/sdm", "ephemeral0")//
@ -223,8 +225,8 @@ public class EC2ComputeServiceLiveTest extends BaseComputeServiceLiveTest {
return instance; return instance;
} }
protected void cleanupExtendedStuff(SecurityGroupClient securityGroupClient, KeyPairClient keyPairClient, String group) protected void cleanupExtendedStuff(SecurityGroupClient securityGroupClient, KeyPairClient keyPairClient,
throws InterruptedException { String group) throws InterruptedException {
try { try {
for (SecurityGroup secgroup : securityGroupClient.describeSecurityGroupsInRegion(null)) for (SecurityGroup secgroup : securityGroupClient.describeSecurityGroupsInRegion(null))
if (secgroup.getName().startsWith("jclouds#" + group) || secgroup.getName().equals(group)) { if (secgroup.getName().startsWith("jclouds#" + group) || secgroup.getName().equals(group)) {

View File

@ -26,7 +26,7 @@ import static org.jclouds.ec2.compute.domain.EC2HardwareBuilder.c1_medium;
import static org.jclouds.ec2.compute.domain.EC2HardwareBuilder.c1_xlarge; import static org.jclouds.ec2.compute.domain.EC2HardwareBuilder.c1_xlarge;
import static org.jclouds.ec2.compute.domain.EC2HardwareBuilder.cc1_4xlarge; import static org.jclouds.ec2.compute.domain.EC2HardwareBuilder.cc1_4xlarge;
import static org.jclouds.ec2.compute.domain.EC2HardwareBuilder.m1_large; import static org.jclouds.ec2.compute.domain.EC2HardwareBuilder.m1_large;
import static org.jclouds.ec2.compute.domain.EC2HardwareBuilder.m1_small; import static org.jclouds.ec2.compute.domain.EC2HardwareBuilder.m1_small32;
import static org.jclouds.ec2.compute.domain.EC2HardwareBuilder.m1_xlarge; import static org.jclouds.ec2.compute.domain.EC2HardwareBuilder.m1_xlarge;
import static org.jclouds.ec2.compute.domain.EC2HardwareBuilder.m2_2xlarge; import static org.jclouds.ec2.compute.domain.EC2HardwareBuilder.m2_2xlarge;
import static org.jclouds.ec2.compute.domain.EC2HardwareBuilder.m2_4xlarge; import static org.jclouds.ec2.compute.domain.EC2HardwareBuilder.m2_4xlarge;
@ -161,7 +161,7 @@ public class EC2TemplateBuilderTest {
.build())); .build()));
Supplier<Set<? extends Hardware>> sizes = Suppliers.<Set<? extends Hardware>> ofInstance(ImmutableSet Supplier<Set<? extends Hardware>> sizes = Suppliers.<Set<? extends Hardware>> ofInstance(ImmutableSet
.<Hardware> of(t1_micro().build(), c1_medium().build(), c1_xlarge().build(), m1_large().build(), .<Hardware> of(t1_micro().build(), c1_medium().build(), c1_xlarge().build(), m1_large().build(),
m1_small().build(), m1_xlarge().build(), m2_xlarge().build(), m2_2xlarge().build(), m1_small32().build(), m1_xlarge().build(), m2_xlarge().build(), m2_2xlarge().build(),
m2_4xlarge().build(), CC1_4XLARGE)); m2_4xlarge().build(), CC1_4XLARGE));
return new TemplateBuilderImpl(locations, images, sizes, Suppliers.ofInstance(location), optionsProvider, return new TemplateBuilderImpl(locations, images, sizes, Suppliers.ofInstance(location), optionsProvider,

View File

@ -18,7 +18,7 @@
*/ */
package org.jclouds.ec2.compute.functions; package org.jclouds.ec2.compute.functions;
import static org.jclouds.ec2.compute.domain.EC2HardwareBuilder.m1_small; import static org.jclouds.ec2.compute.domain.EC2HardwareBuilder.m1_small32;
import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertEquals;
import java.net.UnknownHostException; import java.net.UnknownHostException;
@ -129,7 +129,7 @@ public class RunningInstanceToNodeMetadataTest {
@Test @Test
public void testApplyWhereTagDoesntMatchAndImageHardwareAndLocationFound() throws UnknownHostException { public void testApplyWhereTagDoesntMatchAndImageHardwareAndLocationFound() throws UnknownHostException {
RunningInstanceToNodeMetadata parser = createNodeParser(ImmutableSet.of(m1_small().build()), ImmutableSet RunningInstanceToNodeMetadata parser = createNodeParser(ImmutableSet.of(m1_small32().build()), ImmutableSet
.of(provider), EC2ImageParserTest.convertImages("/amzn_images.xml"), ImmutableMap .of(provider), EC2ImageParserTest.convertImages("/amzn_images.xml"), ImmutableMap
.<String, Credentials> of()); .<String, Credentials> of());
@ -137,7 +137,7 @@ public class RunningInstanceToNodeMetadataTest {
assertEquals(parser.apply(server), new NodeMetadataBuilder().state(NodeState.RUNNING).privateAddresses( assertEquals(parser.apply(server), new NodeMetadataBuilder().state(NodeState.RUNNING).privateAddresses(
ImmutableSet.of("10.243.42.70")).publicAddresses(ImmutableSet.of("174.129.81.68")).imageId( ImmutableSet.of("10.243.42.70")).publicAddresses(ImmutableSet.of("174.129.81.68")).imageId(
"us-east-1/ami-82e4b5c7").hardware(m1_small().build()).operatingSystem( "us-east-1/ami-82e4b5c7").hardware(m1_small32().build()).operatingSystem(
new OperatingSystem.Builder().family(OsFamily.UNRECOGNIZED).version("").arch("paravirtual").description( new OperatingSystem.Builder().family(OsFamily.UNRECOGNIZED).version("").arch("paravirtual").description(
"137112412989/amzn-ami-0.9.7-beta.i386-ebs").is64Bit(false).build()).id("us-east-1/i-0799056f") "137112412989/amzn-ami-0.9.7-beta.i386-ebs").is64Bit(false).build()).id("us-east-1/i-0799056f")
.providerId("i-0799056f").location(provider).build()); .providerId("i-0799056f").location(provider).build());
@ -158,7 +158,7 @@ public class RunningInstanceToNodeMetadataTest {
}; };
Map<RegionAndName, Image> instanceToImage = new MapMaker().makeComputingMap(nullReturningFunction); Map<RegionAndName, Image> instanceToImage = new MapMaker().makeComputingMap(nullReturningFunction);
RunningInstanceToNodeMetadata parser = createNodeParser(ImmutableSet.of(m1_small().build()), ImmutableSet RunningInstanceToNodeMetadata parser = createNodeParser(ImmutableSet.of(m1_small32().build()), ImmutableSet
.of(provider), ImmutableMap.<String, Credentials> of(), .of(provider), ImmutableMap.<String, Credentials> of(),
EC2ComputeServiceDependenciesModule.instanceToNodeState, instanceToImage); EC2ComputeServiceDependenciesModule.instanceToNodeState, instanceToImage);
@ -167,7 +167,7 @@ public class RunningInstanceToNodeMetadataTest {
assertEquals(parser.apply(server), new NodeMetadataBuilder().state(NodeState.RUNNING).privateAddresses( assertEquals(parser.apply(server), new NodeMetadataBuilder().state(NodeState.RUNNING).privateAddresses(
ImmutableSet.of("10.243.42.70")).publicAddresses(ImmutableSet.of("174.129.81.68")).imageId( ImmutableSet.of("10.243.42.70")).publicAddresses(ImmutableSet.of("174.129.81.68")).imageId(
"us-east-1/ami-82e4b5c7").id("us-east-1/i-0799056f").providerId("i-0799056f").hardware( "us-east-1/ami-82e4b5c7").id("us-east-1/i-0799056f").providerId("i-0799056f").hardware(
m1_small().build()).location(provider).build()); m1_small32().build()).location(provider).build());
} }
protected RunningInstance firstInstanceFromResource(String resource) { protected RunningInstance firstInstanceFromResource(String resource) {

View File

@ -69,7 +69,7 @@ public class CreateKeyPairAndSecurityGroupsAsNeededAndReturnRunOptionsTest {
// setup constants // setup constants
String region = Region.AP_SOUTHEAST_1; String region = Region.AP_SOUTHEAST_1;
String tag = "tag"; String tag = "tag";
Hardware size = EC2HardwareBuilder.m1_small().build(); Hardware size = EC2HardwareBuilder.m1_small32().build();
String systemGeneratedKeyPairName = "systemGeneratedKeyPair"; String systemGeneratedKeyPairName = "systemGeneratedKeyPair";
String generatedGroup = "group"; String generatedGroup = "group";
Set<String> generatedGroups = ImmutableSet.of(generatedGroup); Set<String> generatedGroups = ImmutableSet.of(generatedGroup);
@ -124,7 +124,7 @@ public class CreateKeyPairAndSecurityGroupsAsNeededAndReturnRunOptionsTest {
// setup constants // setup constants
String region = Region.AP_SOUTHEAST_1; String region = Region.AP_SOUTHEAST_1;
String tag = "tag"; String tag = "tag";
Hardware size = EC2HardwareBuilder.m1_small().build(); Hardware size = EC2HardwareBuilder.m1_small32().build();
String systemGeneratedKeyPairName = "systemGeneratedKeyPair"; String systemGeneratedKeyPairName = "systemGeneratedKeyPair";
String generatedGroup = "group"; String generatedGroup = "group";
Set<String> generatedGroups = ImmutableSet.of(generatedGroup); Set<String> generatedGroups = ImmutableSet.of(generatedGroup);

View File

@ -159,8 +159,8 @@ public class ElasticStackClientLiveTest {
@Test @Test
public void testGetDrive() throws Exception { public void testGetDrive() throws Exception {
for (String driveUUID : client.listDrives()) { for (String driveUUID : client.listDrives()) {
assert !"".equals(driveUUID); assert !"".equals(driveUUID) : driveUUID;
assertNotNull(client.getDriveInfo(driveUUID)); assert client.getDriveInfo(driveUUID) != null : driveUUID;
} }
} }

View File

@ -18,13 +18,23 @@
*/ */
package org.jclouds.openstack.swift.config; package org.jclouds.openstack.swift.config;
import java.net.URI;
import java.util.concurrent.Future;
import javax.inject.Inject;
import javax.inject.Named;
import javax.inject.Singleton; import javax.inject.Singleton;
import org.jclouds.Constants;
import org.jclouds.http.RequiresHttp; import org.jclouds.http.RequiresHttp;
import org.jclouds.openstack.OpenStackAuthAsyncClient.AuthenticationResponse;
import org.jclouds.openstack.config.OpenStackAuthenticationModule.GetAuthenticationResponse;
import org.jclouds.openstack.reference.AuthHeaders;
import org.jclouds.openstack.swift.CommonSwiftAsyncClient; import org.jclouds.openstack.swift.CommonSwiftAsyncClient;
import org.jclouds.openstack.swift.CommonSwiftClient; import org.jclouds.openstack.swift.CommonSwiftClient;
import org.jclouds.openstack.swift.SwiftAsyncClient; import org.jclouds.openstack.swift.SwiftAsyncClient;
import org.jclouds.openstack.swift.SwiftClient; import org.jclouds.openstack.swift.SwiftClient;
import org.jclouds.rest.AsyncClientFactory;
import org.jclouds.rest.ConfiguresRestClient; import org.jclouds.rest.ConfiguresRestClient;
import com.google.inject.Provides; import com.google.inject.Provides;
@ -52,4 +62,28 @@ public class SwiftRestClientModule extends BaseSwiftRestClientModule<SwiftClient
CommonSwiftAsyncClient provideCommonSwiftClient(SwiftAsyncClient in) { CommonSwiftAsyncClient provideCommonSwiftClient(SwiftAsyncClient in) {
return in; return in;
} }
@Singleton
public static class GetAuthenticationResponseForStorage extends GetAuthenticationResponse {
@Inject
public GetAuthenticationResponseForStorage(AsyncClientFactory factory,
@Named(Constants.PROPERTY_IDENTITY) String user, @Named(Constants.PROPERTY_CREDENTIAL) String key) {
super(factory, user, key);
}
protected Future<AuthenticationResponse> authenticate() {
return client.authenticateStorage(user, key);
}
}
protected URI provideStorageUrl(AuthenticationResponse response) {
return response.getServices().get(AuthHeaders.STORAGE_URL);
}
@Override
protected void configure() {
bind(GetAuthenticationResponse.class).to(GetAuthenticationResponseForStorage.class);
super.configure();
}
} }

View File

@ -67,50 +67,47 @@ public class VCloudDestroyNodeStrategy implements DestroyNodeStrategy {
VApp vApp = client.getVAppClient().getVApp(vappId); VApp vApp = client.getVAppClient().getVApp(vappId);
if (vApp == null) if (vApp == null)
return null; return null;
vApp = powerOffVAppIfDeployed(vApp);
waitForPendingTasksToComplete(vApp);
vApp = undeployVAppIfDeployed(vApp); vApp = undeployVAppIfDeployed(vApp);
deleteVApp(vappId); deleteVApp(vApp);
try { try {
return getNode.getNode(id); return getNode.getNode(id);
} catch (AuthorizationException e) { } catch (AuthorizationException e) {
// vcloud bug will sometimes throw an exception getting the vapp right after deleting it.
logger.trace("authorization error getting %s after deletion: %s", id, e.getMessage()); logger.trace("authorization error getting %s after deletion: %s", id, e.getMessage());
return null; return null;
} }
} }
void deleteVApp(URI vappId) { void waitForPendingTasksToComplete(VApp vApp) {
logger.debug(">> deleting vApp(%s)", vappId); for (Task task : vApp.getTasks())
Task task = client.getVAppClient().deleteVApp(vappId); waitForTask(task, vApp);
if (!successTester.apply(task.getHref())) {
throw new RuntimeException(String.format("failed to %s %s: %s", "delete", vappId, task));
} }
logger.debug("<< deleted vApp(%s)", vappId);
public void waitForTask(Task task, VApp vAppResponse) {
if (!successTester.apply(task.getHref())) {
throw new RuntimeException(String.format("failed to %s %s: %s", task.getName(), vAppResponse.getName(), task));
}
}
void deleteVApp(VApp vApp) {
logger.debug(">> deleting vApp(%s)", vApp.getHref());
waitForTask(client.getVAppClient().deleteVApp(vApp.getHref()), vApp);
logger.debug("<< deleted vApp(%s)", vApp.getHref());
} }
VApp undeployVAppIfDeployed(VApp vApp) { VApp undeployVAppIfDeployed(VApp vApp) {
if (vApp.getStatus().compareTo(Status.RESOLVED) > 0) { if (vApp.getStatus() != Status.OFF) {
logger.debug(">> undeploying vApp(%s), current status: %s", vApp.getName(), vApp.getStatus()); logger.debug(">> undeploying vApp(%s), current status: %s", vApp.getName(), vApp.getStatus());
Task task = client.getVAppClient().undeployVApp(vApp.getHref()); try {
if (!successTester.apply(task.getHref())) { waitForTask(client.getVAppClient().undeployVApp(vApp.getHref()), vApp);
// TODO timeout
throw new RuntimeException(String.format("failed to %s %s: %s", "undeploy", vApp.getName(), task));
}
vApp = client.getVAppClient().getVApp(vApp.getHref()); vApp = client.getVAppClient().getVApp(vApp.getHref());
logger.debug("<< %s vApp(%s)", vApp.getStatus(), vApp.getName()); logger.debug("<< %s vApp(%s)", vApp.getStatus(), vApp.getName());
} catch (IllegalStateException e) {
logger.warn(e, "<< %s vApp(%s)", vApp.getStatus(), vApp.getName());
} }
return vApp;
}
VApp powerOffVAppIfDeployed(VApp vApp) {
if (vApp.getStatus().compareTo(Status.OFF) > 0) {
logger.debug(">> powering off vApp(%s), current status: %s", vApp.getName(), vApp.getStatus());
Task task = client.getVAppClient().powerOffVApp(vApp.getHref());
if (!successTester.apply(task.getHref())) {
// TODO timeout
throw new RuntimeException(String.format("failed to %s %s: %s", "powerOff", vApp.getName(), task));
}
vApp = client.getVAppClient().getVApp(vApp.getHref());
logger.debug("<< %s vApp(%s)", vApp.getStatus(), vApp.getName());
} }
return vApp; return vApp;
} }

View File

@ -34,7 +34,9 @@ import org.jclouds.vcloud.domain.Catalog;
import org.jclouds.vcloud.domain.CatalogItem; import org.jclouds.vcloud.domain.CatalogItem;
import org.jclouds.vcloud.domain.Org; import org.jclouds.vcloud.domain.Org;
import org.jclouds.vcloud.domain.ReferenceType; import org.jclouds.vcloud.domain.ReferenceType;
import org.jclouds.vcloud.domain.Status;
import org.jclouds.vcloud.domain.Task; import org.jclouds.vcloud.domain.Task;
import org.jclouds.vcloud.domain.VApp;
import org.jclouds.vcloud.domain.VAppTemplate; import org.jclouds.vcloud.domain.VAppTemplate;
import org.jclouds.vcloud.options.CatalogItemOptions; import org.jclouds.vcloud.options.CatalogItemOptions;
import org.jclouds.vcloud.predicates.TaskSuccess; import org.jclouds.vcloud.predicates.TaskSuccess;
@ -125,20 +127,17 @@ public class VAppTemplateClientLiveTest extends BaseVCloudClientLiveTest {
Predicate<URI> taskTester = new RetryablePredicate<URI>(new TaskSuccess(getVCloudApi()), 600, 5, Predicate<URI> taskTester = new RetryablePredicate<URI>(new TaskSuccess(getVCloudApi()), 600, 5,
TimeUnit.SECONDS); TimeUnit.SECONDS);
// I have to powerOff first
Task task = getVCloudApi().getVAppClient().powerOffVApp(URI.create(node.getId()));
// wait up to ten minutes per above
assert taskTester.apply(task.getHref()) : node;
// having a problem where the api is returning an error telling us to stop!
// I have to undeploy first // I have to undeploy first
task = getVCloudApi().getVAppClient().undeployVApp(URI.create(node.getId())); Task task = getVCloudApi().getVAppClient().undeployVApp(URI.create(node.getId()));
// wait up to ten minutes per above // wait up to ten minutes per above
assert taskTester.apply(task.getHref()) : node; assert taskTester.apply(task.getHref()) : node;
VApp vApp = getVCloudApi().getVAppClient().getVApp(URI.create(node.getId()));
// wait up to ten minutes per above
assertEquals(vApp.getStatus(), Status.OFF);
// vdc is equiv to the node's location // vdc is equiv to the node's location
// vapp uri is the same as the node's id // vapp uri is the same as the node's id
vappTemplate = getVCloudApi().getVAppTemplateClient().captureVAppAsTemplateInVDC(URI.create(node.getId()), vappTemplate = getVCloudApi().getVAppTemplateClient().captureVAppAsTemplateInVDC(URI.create(node.getId()),
@ -159,7 +158,7 @@ public class VAppTemplateClientLiveTest extends BaseVCloudClientLiveTest {
assertEquals(item.getName(), "fooname"); assertEquals(item.getName(), "fooname");
assertEquals(item.getDescription(), "description"); assertEquals(item.getDescription(), "description");
assertEquals(item.getProperties(), ImmutableMap.of("foo", "bar")); assertEquals(item.getProperties(), ImmutableMap.of("foo", "bar"));
assertEquals(item.getEntity().getName(), vappTemplate.getName()); assertEquals(item.getEntity().getName(), "fooname");
assertEquals(item.getEntity().getHref(), vappTemplate.getHref()); assertEquals(item.getEntity().getHref(), vappTemplate.getHref());
assertEquals(item.getEntity().getType(), vappTemplate.getType()); assertEquals(item.getEntity().getType(), vappTemplate.getType());

View File

@ -161,9 +161,9 @@ public class VmClientLiveTest extends BaseVCloudClientLiveTest {
} }
protected void checkVmOutput(String fooTxtContentsMadeByVMwareTools, String decodedVMwareToolsOutput) { protected void checkVmOutput(String fooTxtContentsMadeByVMwareTools, String decodedVMwareToolsOutput) {
assertEquals(decodedVMwareToolsOutput, script);
// note that vmwaretools throws in \r characters when executing scripts // note that vmwaretools throws in \r characters when executing scripts
assertEquals(fooTxtContentsMadeByVMwareTools, iLoveAscii + "\r\n"); assertEquals(fooTxtContentsMadeByVMwareTools, iLoveAscii + "\r\n");
assertEquals(decodedVMwareToolsOutput, script);
} }
protected IPSocket getSocket(NodeMetadata node) { protected IPSocket getSocket(NodeMetadata node) {

View File

@ -94,8 +94,7 @@ public class ParseSystemAndUserMetadataFromHeaders implements Function<HttpRespo
if (lastModified == null) { if (lastModified == null) {
// scaleup-storage uses the wrong case for the last modified header // scaleup-storage uses the wrong case for the last modified header
if ((lastModified = from.getFirstHeaderOrNull("Last-modified")) == null) if ((lastModified = from.getFirstHeaderOrNull("Last-modified")) == null)
throw new HttpException(HttpHeaders.LAST_MODIFIED + " header not present in response: " throw new HttpException(HttpHeaders.LAST_MODIFIED + " header not present in response: " + from);
+ from.getStatusLine());
} }
// Walrus // Walrus

View File

@ -93,4 +93,10 @@ public interface OpenStackAuthAsyncClient {
@ResponseParser(ParseAuthenticationResponseFromHeaders.class) @ResponseParser(ParseAuthenticationResponseFromHeaders.class)
ListenableFuture<AuthenticationResponse> authenticate(@HeaderParam(AuthHeaders.AUTH_USER) String user, ListenableFuture<AuthenticationResponse> authenticate(@HeaderParam(AuthHeaders.AUTH_USER) String user,
@HeaderParam(AuthHeaders.AUTH_KEY) String key); @HeaderParam(AuthHeaders.AUTH_KEY) String key);
@GET
@ResponseParser(ParseAuthenticationResponseFromHeaders.class)
ListenableFuture<AuthenticationResponse> authenticateStorage(@HeaderParam(AuthHeaders.STORAGE_USER) String user,
@HeaderParam(AuthHeaders.STORAGE_PASS) String key);
} }

View File

@ -24,6 +24,7 @@ import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException; import java.util.concurrent.TimeoutException;
import javax.inject.Inject;
import javax.inject.Named; import javax.inject.Named;
import javax.inject.Singleton; import javax.inject.Singleton;
@ -69,17 +70,24 @@ public class OpenStackAuthenticationModule extends AbstractModule {
}; };
} }
@Provides
@Singleton @Singleton
Supplier<AuthenticationResponse> provideAuthenticationResponseCache(final AsyncClientFactory factory, public static class GetAuthenticationResponse implements Supplier<AuthenticationResponse> {
@Named(Constants.PROPERTY_IDENTITY) final String user, protected final OpenStackAuthAsyncClient client;
@Named(Constants.PROPERTY_CREDENTIAL) final String key) { protected final String user;
return Suppliers.memoizeWithExpiration(new RetryOnTimeOutExceptionSupplier<AuthenticationResponse>( protected final String key;
new Supplier<AuthenticationResponse>() {
@Inject
public GetAuthenticationResponse(AsyncClientFactory factory, @Named(Constants.PROPERTY_IDENTITY) String user,
@Named(Constants.PROPERTY_CREDENTIAL) String key) {
this.client = factory.create(OpenStackAuthAsyncClient.class);
this.user = user;
this.key = key;
}
@Override
public AuthenticationResponse get() { public AuthenticationResponse get() {
try { try {
Future<AuthenticationResponse> response = factory.create(OpenStackAuthAsyncClient.class) Future<AuthenticationResponse> response = authenticate();
.authenticate(user, key);
return response.get(30, TimeUnit.SECONDS); return response.get(30, TimeUnit.SECONDS);
} catch (Exception e) { } catch (Exception e) {
Throwables.propagate(e); Throwables.propagate(e);
@ -87,7 +95,19 @@ public class OpenStackAuthenticationModule extends AbstractModule {
return null; return null;
} }
} }
}), 23, TimeUnit.HOURS);
protected Future<AuthenticationResponse> authenticate() {
return client.authenticate(user, key);
}
}
@Provides
@Singleton
Supplier<AuthenticationResponse> provideAuthenticationResponseCache(
final GetAuthenticationResponse getAuthenticationResponse) {
return Suppliers.memoizeWithExpiration(new RetryOnTimeOutExceptionSupplier<AuthenticationResponse>(
getAuthenticationResponse), 23, TimeUnit.HOURS);
} }
@Provides @Provides

View File

@ -29,6 +29,8 @@ public interface AuthHeaders {
public static final String AUTH_USER = "X-Auth-User"; public static final String AUTH_USER = "X-Auth-User";
public static final String AUTH_KEY = "X-Auth-Key"; public static final String AUTH_KEY = "X-Auth-Key";
public static final String STORAGE_USER = "X-Storage-User";
public static final String STORAGE_PASS = "X-Storage-Pass";
public static final String AUTH_TOKEN = "X-Auth-Token"; public static final String AUTH_TOKEN = "X-Auth-Token";
public static final String URL_SUFFIX = "-Url"; public static final String URL_SUFFIX = "-Url";

View File

@ -60,6 +60,20 @@ public class OpenStackAuthAsyncClientTest extends RestClientTest<OpenStackAuthAs
} }
public void testAuthenticateStorage() throws SecurityException, NoSuchMethodException, IOException {
Method method = OpenStackAuthAsyncClient.class.getMethod("authenticateStorage", String.class, String.class);
HttpRequest httpRequest = processor.createRequest(method, "foo", "bar");
assertRequestLineEquals(httpRequest, "GET http://localhost:8080/v1.0 HTTP/1.1");
assertNonPayloadHeadersEqual(httpRequest, "X-Storage-Pass: bar\nX-Storage-User: foo\n");
assertPayloadEquals(httpRequest, null, null, false);
assertResponseParserClassEquals(method, httpRequest, ParseAuthenticationResponseFromHeaders.class);
assertSaxResponseParserClassEquals(method, null);
assertExceptionParserClassEquals(method, MapHttp4xxCodesToExceptions.class);
}
@Override @Override
public RestContextSpec<OpenStackAuthClient, OpenStackAuthAsyncClient> createContextSpec() { public RestContextSpec<OpenStackAuthClient, OpenStackAuthAsyncClient> createContextSpec() {
return contextSpec("test", "http://localhost:8080", "1.0", "", "identity", "credential", return contextSpec("test", "http://localhost:8080", "1.0", "", "identity", "credential",

View File

@ -18,15 +18,16 @@
*/ */
package org.jclouds.vcloud.terremark.compute; package org.jclouds.vcloud.terremark.compute;
import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.collect.Iterables.filter; import static com.google.common.collect.Iterables.filter;
import static com.google.common.collect.Iterables.getLast; import static com.google.common.collect.Iterables.getLast;
import static org.jclouds.vcloud.terremark.options.AddInternetServiceOptions.Builder.withDescription; import static org.jclouds.vcloud.terremark.options.AddInternetServiceOptions.Builder.withDescription;
import java.net.URI; import java.net.URI;
import java.util.Map; import java.util.Map;
import java.util.Map.Entry;
import java.util.NoSuchElementException; import java.util.NoSuchElementException;
import java.util.Set; import java.util.Set;
import java.util.Map.Entry;
import javax.annotation.Nullable; import javax.annotation.Nullable;
import javax.inject.Inject; import javax.inject.Inject;
@ -142,16 +143,12 @@ public class TerremarkVCloudComputeClient extends VCloudExpressComputeClientImpl
} else { } else {
logger.debug(">> adding InternetService %s:%s:%d", ip.getAddress(), protocol, port); logger.debug(">> adding InternetService %s:%s:%d", ip.getAddress(), protocol, port);
is = client.addInternetServiceToExistingIp( is = client.addInternetServiceToExistingIp(ip.getId(), vApp.getName() + "-" + port, protocol, port,
ip.getId(),
vApp.getName() + "-" + port,
protocol,
port,
withDescription(String.format("port %d access to serverId: %s name: %s", port, vApp.getName(), withDescription(String.format("port %d access to serverId: %s name: %s", port, vApp.getName(),
vApp.getName()))); vApp.getName())));
} }
logger.debug("<< created InternetService(%s) %s:%s:%d", is.getName(), is.getPublicIpAddress().getAddress(), logger.debug("<< created InternetService(%s) %s:%s:%d", is.getName(), is.getPublicIpAddress().getAddress(), is
is.getProtocol(), is.getPort()); .getProtocol(), is.getPort());
logger.debug(">> adding Node %s:%d -> %s:%d", is.getPublicIpAddress().getAddress(), is.getPort(), logger.debug(">> adding Node %s:%d -> %s:%d", is.getPublicIpAddress().getAddress(), is.getPort(),
privateAddress, port); privateAddress, port);
Node node = client.addNode(is.getId(), privateAddress, vApp.getName() + "-" + port, port); Node node = client.addNode(is.getId(), privateAddress, vApp.getName() + "-" + port, port);
@ -161,6 +158,7 @@ public class TerremarkVCloudComputeClient extends VCloudExpressComputeClientImpl
} }
private Set<PublicIpAddress> deleteInternetServicesAndNodesAssociatedWithVApp(VCloudExpressVApp vApp) { private Set<PublicIpAddress> deleteInternetServicesAndNodesAssociatedWithVApp(VCloudExpressVApp vApp) {
checkNotNull(vApp.getVDC(), "VDC reference missing for vApp(%s)", vApp.getName());
Set<PublicIpAddress> ipAddresses = Sets.newHashSet(); Set<PublicIpAddress> ipAddresses = Sets.newHashSet();
SERVICE: for (InternetService service : client.getAllInternetServicesInVDC(vApp.getVDC().getHref())) { SERVICE: for (InternetService service : client.getAllInternetServicesInVDC(vApp.getVDC().getHref())) {
for (Node node : client.getNodes(service.getId())) { for (Node node : client.getNodes(service.getId())) {

View File

@ -88,14 +88,16 @@ public abstract class TerremarkClientLiveTest extends VCloudExpressClientLiveTes
protected TerremarkVCloudClient tmClient; protected TerremarkVCloudClient tmClient;
protected Factory sshFactory; protected Factory sshFactory;
private String publicIp; protected String publicIp;
private InternetService is; protected InternetService is;
private Node node; protected Node node;
private VCloudExpressVApp vApp; protected VCloudExpressVApp vApp;
private RetryablePredicate<IPSocket> socketTester; protected RetryablePredicate<IPSocket> socketTester;
private RetryablePredicate<URI> successTester; protected RetryablePredicate<URI> successTester;
private VCloudExpressVApp clone; protected Injector injector;
private VDC vdc;
protected VCloudExpressVApp clone;
protected VDC vdc;
public static final String PREFIX = System.getProperty("user.name") + "-terremark"; public static final String PREFIX = System.getProperty("user.name") + "-terremark";
@Test @Test
@ -281,7 +283,7 @@ public abstract class TerremarkClientLiveTest extends VCloudExpressClientLiveTes
loopAndCheckPass(); loopAndCheckPass();
} }
private void loopAndCheckPass() throws IOException { protected void loopAndCheckPass() throws IOException {
for (int i = 0; i < 5; i++) {// retry loop TODO replace with predicate. for (int i = 0; i < 5; i++) {// retry loop TODO replace with predicate.
try { try {
doCheckPass(publicIp); doCheckPass(publicIp);
@ -373,7 +375,7 @@ public abstract class TerremarkClientLiveTest extends VCloudExpressClientLiveTes
loopAndCheckPass(); loopAndCheckPass();
} }
private void verifyConfigurationOfVApp(VCloudExpressVApp vApp, String serverName, String expectedOs, protected void verifyConfigurationOfVApp(VCloudExpressVApp vApp, String serverName, String expectedOs,
int processorCount, long memory, long hardDisk) { int processorCount, long memory, long hardDisk) {
assertEquals(vApp.getName(), serverName); assertEquals(vApp.getName(), serverName);
assertEquals(vApp.getOperatingSystemDescription(), expectedOs); assertEquals(vApp.getOperatingSystemDescription(), expectedOs);
@ -387,7 +389,7 @@ public abstract class TerremarkClientLiveTest extends VCloudExpressClientLiveTes
CIMPredicates.resourceTypeIn(ResourceType.DISK_DRIVE)).getVirtualQuantity().longValue()); CIMPredicates.resourceTypeIn(ResourceType.DISK_DRIVE)).getVirtualQuantity().longValue());
} }
private void doCheckPass(String address) throws IOException { protected void doCheckPass(String address) throws IOException {
IPSocket socket = new IPSocket(address, 22); IPSocket socket = new IPSocket(address, 22);
System.out.printf("%d: %s awaiting ssh service to start%n", System.currentTimeMillis(), socket); System.out.printf("%d: %s awaiting ssh service to start%n", System.currentTimeMillis(), socket);
@ -466,7 +468,7 @@ public abstract class TerremarkClientLiveTest extends VCloudExpressClientLiveTes
setupCredentials(); setupCredentials();
Properties overrides = setupProperties(); Properties overrides = setupProperties();
Injector injector = new RestContextFactory().createContextBuilder(provider, injector = new RestContextFactory().createContextBuilder(provider,
ImmutableSet.<Module> of(new Log4JLoggingModule(), new JschSshClientModule()), overrides) ImmutableSet.<Module> of(new Log4JLoggingModule(), new JschSshClientModule()), overrides)
.buildInjector(); .buildInjector();

View File

@ -87,6 +87,7 @@ import org.jclouds.vcloud.predicates.TaskSuccess;
import com.google.common.base.Function; import com.google.common.base.Function;
import com.google.common.base.Predicate; import com.google.common.base.Predicate;
import com.google.common.base.Predicates;
import com.google.common.base.Supplier; import com.google.common.base.Supplier;
import com.google.common.collect.Iterables; import com.google.common.collect.Iterables;
import com.google.inject.ConfigurationException; import com.google.inject.ConfigurationException;
@ -451,12 +452,14 @@ public class CommonVCloudRestClientModule<S extends CommonVCloudClient, A extend
checkState(networks.size() > 0, "No networks present in vDC: " + vDC.getName()); checkState(networks.size() > 0, "No networks present in vDC: " + vDC.getName());
if (networks.size() == 1) if (networks.size() == 1)
return Iterables.getLast(networks.values()).getHref(); return Iterables.getLast(networks.values()).getHref();
String networkName = null;
try { try {
String networkName = injector.getInstance(Key.get(String.class, Names networkName = injector.getInstance(Key.get(String.class, Names.named(PROPERTY_VCLOUD_DEFAULT_NETWORK)));
.named(PROPERTY_VCLOUD_DEFAULT_NETWORK))); ReferenceType network = networks.get(Iterables.find(networks.keySet(), Predicates
ReferenceType network = networks.get(networkName); .containsPattern(networkName)));
checkState(network != null, String.format("network named %s not in %s", networkName, networks.keySet()));
return network.getHref(); return network.getHref();
} catch (NoSuchElementException e) {
throw new IllegalStateException(String.format("network matching [%s] not in %s", networkName, networks.keySet()));
} catch (ConfigurationException e) { } catch (ConfigurationException e) {
return findDefaultNetworkForVDC(vDC, networks, injector); return findDefaultNetworkForVDC(vDC, networks, injector);
} }

View File

@ -18,10 +18,10 @@
*/ */
package org.jclouds.vcloud.functions; package org.jclouds.vcloud.functions;
import static com.google.common.base.Preconditions.checkNotNull;
import static org.jclouds.http.HttpUtils.releasePayload; import static org.jclouds.http.HttpUtils.releasePayload;
import java.util.Map; import java.util.Map;
import java.util.NoSuchElementException;
import java.util.regex.Matcher; import java.util.regex.Matcher;
import java.util.regex.Pattern; import java.util.regex.Pattern;
@ -41,6 +41,8 @@ import org.jclouds.vcloud.endpoints.Org;
import org.jclouds.vcloud.xml.OrgListHandler; import org.jclouds.vcloud.xml.OrgListHandler;
import com.google.common.base.Function; import com.google.common.base.Function;
import com.google.common.base.Predicates;
import com.google.common.collect.Iterables;
/** /**
* This parses {@link VCloudSession} from HTTP headers. * This parses {@link VCloudSession} from HTTP headers.
@ -49,7 +51,7 @@ 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;
@ -61,26 +63,18 @@ public class ParseLoginResponseFromHeaders implements Function<HttpResponse, VCl
} }
/** /**
* parses the http response headers to create a new {@link VCloudSession} * parses the http response headers to create a new {@link VCloudSession} object.
* object.
*/ */
public VCloudSession apply(HttpResponse from) { public VCloudSession apply(HttpResponse from) {
String cookieHeader = from.getFirstHeaderOrNull("x-vcloud-authorization");
if (cookieHeader == null)
cookieHeader = from.getFirstHeaderOrNull(HttpHeaders.SET_COOKIE);
checkNotNull(cookieHeader, "Header %s or %s must be present", "x-vcloud-authorization", HttpHeaders.SET_COOKIE);
final Matcher matcher = pattern.matcher(cookieHeader);
boolean matchFound = matcher.find();
try { try {
if (matchFound) { final String token = parseTokenFromHeaders(from);
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(2); return token;
} }
@Org @Org
@ -88,11 +82,26 @@ public class ParseLoginResponseFromHeaders implements Function<HttpResponse, VCl
return org; return org;
} }
}; };
}
} finally { } finally {
releasePayload(from); releasePayload(from);
} }
throw new HttpResponseException("x-vcloud-authorization not found ", null, from); }
public String parseTokenFromHeaders(HttpResponse from) {
String cookieHeader = from.getFirstHeaderOrNull("x-vcloud-authorization");
if (cookieHeader != null) {
Matcher matcher = pattern.matcher(cookieHeader);
return matcher.find() ? matcher.group(2) : cookieHeader;
} else {
try {
cookieHeader = Iterables.find(from.getHeaders().get(HttpHeaders.SET_COOKIE), Predicates.contains(pattern));
Matcher matcher = pattern.matcher(cookieHeader);
matcher.find();
return matcher.group(2);
} catch (NoSuchElementException e) {
throw new HttpResponseException(String.format("Header %s or %s must be present", "x-vcloud-authorization",
HttpHeaders.SET_COOKIE), null, from);
}
}
} }
} }

View File

@ -88,8 +88,9 @@ public class ParseVCloudErrorFromHttpResponse implements HttpErrorHandler {
switch (response.getStatusCode()) { switch (response.getStatusCode()) {
case 400: case 400:
if (error != null && error.getMinorErrorCode() != null if (error != null
&& error.getMinorErrorCode() == MinorCode.BUSY_ENTITY) && (error.getMinorErrorCode() != null && error.getMinorErrorCode() == MinorCode.BUSY_ENTITY)
|| (error.getMessage() != null && error.getMessage().indexOf("is not running") != -1))
exception = new IllegalStateException(message, exception); exception = new IllegalStateException(message, exception);
else else
exception = new IllegalArgumentException(message, exception); exception = new IllegalArgumentException(message, exception);

View File

@ -23,6 +23,7 @@ import static org.testng.Assert.assertEquals;
import java.net.URI; import java.net.URI;
import org.jclouds.http.HttpResponse; import org.jclouds.http.HttpResponse;
import org.jclouds.http.HttpResponseException;
import org.jclouds.http.functions.BaseHandlerTest; import org.jclouds.http.functions.BaseHandlerTest;
import org.jclouds.io.Payloads; import org.jclouds.io.Payloads;
import org.jclouds.vcloud.VCloudMediaType; import org.jclouds.vcloud.VCloudMediaType;
@ -96,6 +97,44 @@ public class ParseLoginResponseFromHeadersTest extends BaseHandlerTest {
} }
@Test
public void testApplyTerremarkMultipleCookies() {
HttpResponse response = new HttpResponse(200, "OK", Payloads.newInputStreamPayload(getClass()
.getResourceAsStream("/orglist.xml")), ImmutableMultimap.<String, String> builder().put("Set-Cookie",
"NSC_ESUO_21654_72.46.239.132_443=fooo;expires=Thu, 02-Jun-2011 17:19:26 GMT;path=/;secure;httponly")
.put("Set-Cookie", "vcloud-token=37ce2715-9aba-4f48-8e45-2db8a8da702d; path=/").build());
response.getPayload().getContentMetadata().setContentType("Content-Type: application/xml; charset=utf-8");
response.getPayload().getContentMetadata().setContentLength(307l);
VCloudSession reply = parser.apply(response);
assertEquals(reply.getVCloudToken(), "37ce2715-9aba-4f48-8e45-2db8a8da702d");
assertEquals(reply.getOrgs(), ImmutableMap.of("adrian@jclouds.org", new ReferenceTypeImpl("adrian@jclouds.org",
VCloudMediaType.ORG_XML, URI.create("https://services.vcloudexpress.terremark.com/api/v0.8/org/48"))));
}
@Test(expectedExceptions = HttpResponseException.class)
public void testUnmatchedCookieThrowsHttpResponseException() {
HttpResponse response = new HttpResponse(200, "OK", Payloads.newInputStreamPayload(getClass()
.getResourceAsStream("/orglist.xml")), ImmutableMultimap.<String, String> builder().put("Set-Cookie",
"NSC_ESUO_21654_72.46.239.132_443=fooo;expires=Thu, 02-Jun-2011 17:19:26 GMT;path=/;secure;httponly")
.build());
response.getPayload().getContentMetadata().setContentType("Content-Type: application/xml; charset=utf-8");
response.getPayload().getContentMetadata().setContentLength(307l);
parser.apply(response);
}
@Test(expectedExceptions = HttpResponseException.class)
public void testNoThrowsHttpResponseException() {
HttpResponse response = new HttpResponse(200, "OK", Payloads.newInputStreamPayload(getClass()
.getResourceAsStream("/orglist.xml")), ImmutableMultimap.<String, String> of());
response.getPayload().getContentMetadata().setContentType("Content-Type: application/xml; charset=utf-8");
response.getPayload().getContentMetadata().setContentLength(307l);
parser.apply(response);
}
@Test @Test
public void testApplyVirtacore() { public void testApplyVirtacore() {
HttpResponse response = new HttpResponse(200, "OK", Payloads.newInputStreamPayload(getClass() HttpResponse response = new HttpResponse(200, "OK", Payloads.newInputStreamPayload(getClass()

View File

@ -25,6 +25,7 @@ import org.jclouds.http.HttpErrorHandler;
import org.jclouds.http.HttpResponseException; import org.jclouds.http.HttpResponseException;
import org.jclouds.rest.AuthorizationException; import org.jclouds.rest.AuthorizationException;
import org.jclouds.rest.ResourceNotFoundException; import org.jclouds.rest.ResourceNotFoundException;
import org.jclouds.vcloud.VCloudMediaType;
import org.testng.annotations.Test; import org.testng.annotations.Test;
/** /**
@ -36,23 +37,32 @@ public class ParseVCloudErrorFromHttpResponseTest extends BaseHttpErrorHandlerTe
@Test @Test
public void testGet404SetsResourceNotFoundException() { public void testGet404SetsResourceNotFoundException() {
assertCodeMakes("GET", URI assertCodeMakes("GET", URI.create("https://services.vcloudexpress.terremark.com/api/v0.8a-ext1.6/vdc/32"), 404,
.create("https://services.vcloudexpress.terremark.com/api/v0.8a-ext1.6/vdc/32"), "", "", ResourceNotFoundException.class);
404, "", "", ResourceNotFoundException.class);
} }
@Test @Test
public void testDelete404SetsHttpResponseException() { public void testDelete404SetsHttpResponseException() {
assertCodeMakes("DELETE", URI assertCodeMakes("DELETE", URI.create("https://services.vcloudexpress.terremark.com/api/v0.8a-ext1.6/vdc/32"),
.create("https://services.vcloudexpress.terremark.com/api/v0.8a-ext1.6/vdc/32"),
404, "", "", HttpResponseException.class); 404, "", "", HttpResponseException.class);
} }
@Test
public void testPOSTNotRunningSetsIllegalStateException() {
assertCodeMakes(
"POST",
URI.create("https://vcenterprise.bluelock.com/api/v1.0/vApp/vapp-138351019/action/undeploy"),
400,
"HTTP/1.1 400 Bad Request",
VCloudMediaType.ERROR_XML,
"<Error xmlns=\"http://www.vmware.com/vcloud/v1\" minorErrorCode=\"BAD_REQUEST\" message=\"The requested operation could not be executed since vApp &quot;adriancolecap-78c&quot; is not running.\" majorErrorCode=\"400\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:schemaLocation=\"http://www.vmware.com/vcloud/v1 http://vcenterprise.bluelock.com/api/v1.0/schema/master.xsd\"></Error>\n",
IllegalStateException.class);
}
@Test @Test
public void test401SetsAuthorizationException() { public void test401SetsAuthorizationException() {
assertCodeMakes("GET", URI assertCodeMakes("GET", URI.create("https://services.vcloudexpress.terremark.com/api/v0.8a-ext1.6/vdc/32"), 401,
.create("https://services.vcloudexpress.terremark.com/api/v0.8a-ext1.6/vdc/32"), "", "", AuthorizationException.class);
401, "", "", AuthorizationException.class);
} }
@Override @Override

View File

@ -20,19 +20,22 @@
(ns org.jclouds.compute2 (ns org.jclouds.compute2
"A clojure binding to the jclouds ComputeService. "A clojure binding to the jclouds ComputeService.
Current supported providers are: jclouds supports many compute providers including Amazon EC2 (aws-ec2),
[aws-ec2, eucualyptus-partnercloud-ec2, elastichosts-lon-b, Rackspace Cloud Servers (cloudservers-us), GoGrid (gogrid), and BlueLock
cloudservers-uk, cloudservers-us, byon, cloudsigma-zrh, stub, vCloud (bluelock-vcloud-zone01). There are over a dozen to choose from.
trmk-ecloud, trmk-vcloudexpress, vcloud, bluelock, eucalyptus,
slicehost, elastichosts-lon-p, elastichosts-sat-p, elastichosts, Current supported providers are available via the following dependency:
openhosting-east1, serverlove-z1-man, skalicloud-sdg-my, deltacloud] org.jclouds/jclouds-allcompute
You can inquire about which providers are loaded via the following:
(seq (org.jclouds.providers.Providers/allCompute))
Here's an example of getting some compute configuration from rackspace: Here's an example of getting some compute configuration from rackspace:
(use 'org.jclouds.compute2) (use 'org.jclouds.compute2)
(use 'clojure.pprint) (use 'clojure.pprint)
(def provider \"cloudservers\") (def provider \"cloudservers-us\")
(def provider-identity \"username\") (def provider-identity \"username\")
(def provider-credential \"password\") (def provider-credential \"password\")
@ -225,7 +228,11 @@ Here's an example of creating and running a small linux node in the group webser
(defn destroy-nodes-matching (defn destroy-nodes-matching
"Destroy all the nodes in the fn pred. "Destroy all the nodes in the fn pred.
pred should be a fn of one argument that takes a ComputeMetadata and returns true or false." pred should be a fn of one argument that takes a ComputeMetadata and returns true or false.
;; destroy all nodes
(destroy-nodes-matching compute (constantly true))
"
([#^ComputeService compute pred] ([#^ComputeService compute pred]
(.destroyNodesMatching compute (to-predicate pred)))) (.destroyNodesMatching compute (to-predicate pred))))

View File

@ -18,11 +18,12 @@
; ;
(ns org.jclouds.predicate) (ns org.jclouds.predicate)
(defprotocol Predicate (defprotocol Coercions
"Protocol for making a com.google.common.base.Predicate." "Protocol for coercing between predicate-like things, like
Clojure fns and com.google.common.base.Predicate."
(to-predicate [p])) (to-predicate [p]))
(extend-protocol Predicate (extend-protocol Coercions
clojure.lang.IFn clojure.lang.IFn
(to-predicate [p] (to-predicate [p]
(reify com.google.common.base.Predicate (reify com.google.common.base.Predicate

View File

@ -32,13 +32,17 @@ import org.jclouds.compute.options.RunScriptOptions;
import org.jclouds.compute.reference.ComputeServiceConstants; import org.jclouds.compute.reference.ComputeServiceConstants;
import org.jclouds.logging.Logger; import org.jclouds.logging.Logger;
import org.jclouds.scriptbuilder.InitBuilder; import org.jclouds.scriptbuilder.InitBuilder;
import org.jclouds.scriptbuilder.domain.AppendFile;
import org.jclouds.scriptbuilder.domain.OsFamily; import org.jclouds.scriptbuilder.domain.OsFamily;
import org.jclouds.scriptbuilder.domain.Statement; import org.jclouds.scriptbuilder.domain.Statement;
import org.jclouds.scriptbuilder.domain.Statements;
import org.jclouds.ssh.SshClient; import org.jclouds.ssh.SshClient;
import com.google.common.annotations.VisibleForTesting; import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Function; import com.google.common.base.Function;
import com.google.common.base.Objects; import com.google.common.base.Objects;
import com.google.common.base.Splitter;
import com.google.inject.Inject;
import com.google.inject.assistedinject.Assisted; import com.google.inject.assistedinject.Assisted;
import com.google.inject.assistedinject.AssistedInject; import com.google.inject.assistedinject.AssistedInject;
@ -47,6 +51,7 @@ import com.google.inject.assistedinject.AssistedInject;
* @author Adrian Cole * @author Adrian Cole
*/ */
public class RunScriptOnNodeAsInitScriptUsingSsh implements RunScriptOnNode { public class RunScriptOnNodeAsInitScriptUsingSsh implements RunScriptOnNode {
public static final String PROPERTY_PUSH_INIT_SCRIPT_VIA_SFTP = "jclouds.compute.push-init-script-via-sftp";
@Resource @Resource
@Named(ComputeServiceConstants.COMPUTE_LOGGER) @Named(ComputeServiceConstants.COMPUTE_LOGGER)
protected Logger logger = Logger.NULL; protected Logger logger = Logger.NULL;
@ -59,6 +64,14 @@ public class RunScriptOnNodeAsInitScriptUsingSsh implements RunScriptOnNode {
protected SshClient ssh; protected SshClient ssh;
/**
* true to use sftp, false to use ssh. If there's a problem with the sftp configuration, setting
* this to false will help.
*/
@Inject(optional = true)
@Named(PROPERTY_PUSH_INIT_SCRIPT_VIA_SFTP)
private boolean pushInitViaSftp = true;
@AssistedInject @AssistedInject
public RunScriptOnNodeAsInitScriptUsingSsh(Function<NodeMetadata, SshClient> sshFactory, public RunScriptOnNodeAsInitScriptUsingSsh(Function<NodeMetadata, SshClient> sshFactory,
@Assisted NodeMetadata node, @Assisted Statement script, @Assisted RunScriptOptions options) { @Assisted NodeMetadata node, @Assisted Statement script, @Assisted RunScriptOptions options) {
@ -104,7 +117,13 @@ public class RunScriptOnNodeAsInitScriptUsingSsh implements RunScriptOnNode {
* ssh client is initialized through this call. * ssh client is initialized through this call.
*/ */
protected ExecResponse doCall() { protected ExecResponse doCall() {
if (pushInitViaSftp) {
ssh.put(name, init.render(OsFamily.UNIX)); ssh.put(name, init.render(OsFamily.UNIX));
} else {
ssh.exec("rm " + name);
ssh.exec(Statements.appendFile(name, Splitter.on('\n').split(init.render(OsFamily.UNIX)),
AppendFile.MARKER + "_" + name).render(OsFamily.UNIX));
}
ssh.exec("chmod 755 " + name); ssh.exec("chmod 755 " + name);
runAction("init"); runAction("init");
return runAction("start"); return runAction("start");

View File

@ -416,6 +416,7 @@ public class TemplateBuilderImpl implements TemplateBuilder {
*/ */
@Override @Override
public TemplateBuilder fromTemplate(Template template) { public TemplateBuilder fromTemplate(Template template) {
location = template.getLocation();
fromHardware(template.getHardware()); fromHardware(template.getHardware());
fromImage(template.getImage()); fromImage(template.getImage());
options(template.getOptions()); options(template.getOptions());

View File

@ -561,7 +561,7 @@ public abstract class BaseComputeServiceLiveTest {
} }
} }
protected int nonBlockDuration = 30 * 1000; protected int nonBlockDurationSeconds = 30;
public void testOptionToNotBlock() throws Exception { public void testOptionToNotBlock() throws Exception {
String group = this.group + "block"; String group = this.group + "block";
@ -577,9 +577,9 @@ public abstract class BaseComputeServiceLiveTest {
Set<? extends NodeMetadata> nodes = client.createNodesInGroup(group, 1, options); Set<? extends NodeMetadata> nodes = client.createNodesInGroup(group, 1, options);
NodeMetadata node = getOnlyElement(nodes); NodeMetadata node = getOnlyElement(nodes);
assert node.getState() != NodeState.RUNNING; assert node.getState() != NodeState.RUNNING;
long duration = System.currentTimeMillis() - time; long duration = (System.currentTimeMillis() - time) / 1000;
assert duration < nonBlockDuration : String.format("duration(%d) longer than expected(%d) seconds! ", assert duration < nonBlockDurationSeconds : String.format("duration(%d) longer than expected(%d) seconds! ",
duration / 1000, nonBlockDuration); duration, nonBlockDurationSeconds);
} finally { } finally {
client.destroyNodesMatching(inGroup(group)); client.destroyNodesMatching(inGroup(group));
} }

View File

@ -33,6 +33,7 @@ import java.util.concurrent.TimeoutException;
import org.jclouds.Constants; import org.jclouds.Constants;
import org.jclouds.compute.config.BaseComputeServiceContextModule; import org.jclouds.compute.config.BaseComputeServiceContextModule;
import org.jclouds.compute.domain.Hardware;
import org.jclouds.compute.domain.OsFamily; import org.jclouds.compute.domain.OsFamily;
import org.jclouds.compute.domain.OsFamilyVersion64Bit; import org.jclouds.compute.domain.OsFamilyVersion64Bit;
import org.jclouds.compute.domain.Template; import org.jclouds.compute.domain.Template;
@ -77,6 +78,35 @@ public abstract class BaseTemplateBuilderLiveTest {
apiversion = System.getProperty("test." + provider + ".apiversion"); apiversion = System.getProperty("test." + provider + ".apiversion");
} }
public void testCompareSizes() throws Exception {
Hardware defaultSize = context.getComputeService().templateBuilder().build().getHardware();
Hardware smallest = context.getComputeService().templateBuilder().smallest().build().getHardware();
Hardware fastest = context.getComputeService().templateBuilder().fastest().build().getHardware();
Hardware biggest = context.getComputeService().templateBuilder().biggest().build().getHardware();
System.out.printf("smallest %s%n", smallest);
System.out.printf("fastest %s%n", fastest);
System.out.printf("biggest %s%n", biggest);
assertEquals(defaultSize, smallest);
assert getCores(smallest) <= getCores(fastest) : String.format("%s ! <= %s", smallest, fastest);
assert getCores(biggest) <= getCores(fastest) : String.format("%s ! <= %s", biggest, fastest);
assert biggest.getRam() >= fastest.getRam() : String.format("%s ! >= %s", biggest, fastest);
assert biggest.getRam() >= smallest.getRam() : String.format("%s ! >= %s", biggest, smallest);
assert getCores(fastest) >= getCores(biggest) : String.format("%s ! >= %s", fastest, biggest);
assert getCores(fastest) >= getCores(smallest) : String.format("%s ! >= %s", fastest, smallest);
}
public void testFromTemplate() {
Template defaultTemplate = context.getComputeService().templateBuilder().build();
assertEquals(context.getComputeService().templateBuilder().fromTemplate(defaultTemplate).build().toString(),
defaultTemplate.toString());
}
protected Properties setupProperties() { protected Properties setupProperties() {
Properties overrides = new Properties(); Properties overrides = new Properties();
overrides.setProperty(Constants.PROPERTY_TRUST_ALL_CERTS, "true"); overrides.setProperty(Constants.PROPERTY_TRUST_ALL_CERTS, "true");

View File

@ -0,0 +1,52 @@
/**
*
* 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.date.internal;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
*
* @author Adrian Cole
*/
public class DateUtils {
public static final Pattern NANOS_TO_MILLIS_PATTERN = Pattern.compile(".*[0-9][0-9][0-9][0-9][0-9][0-9]");
public static final Pattern TZ_PATTERN = Pattern.compile("(.*)[+-][0-9][0-9]:?[0-9][0-9]Z?");
public static String trimNanosToMillis(String toParse) {
if (NANOS_TO_MILLIS_PATTERN.matcher(toParse).matches())
toParse = toParse.substring(0, toParse.length() - 3) + 'Z';
return toParse;
}
public static final Pattern SECOND_PATTERN = Pattern.compile(".*[0-2][0-9]:00");
public static String trimTZ(String toParse) {
Matcher matcher = TZ_PATTERN.matcher(toParse);
if (matcher.find()) {
toParse = matcher.group(1) + 'Z';
}
if (toParse.length() == 25 && SECOND_PATTERN.matcher(toParse).matches())
toParse = toParse.substring(0, toParse.length() - 6) + 'Z';
return toParse;
}
}

View File

@ -17,18 +17,16 @@
* ==================================================================== * ====================================================================
*/ */
package org.jclouds.date.internal; package org.jclouds.date.internal;
import static org.jclouds.date.internal.DateUtils.trimNanosToMillis;
import static org.jclouds.date.internal.DateUtils.trimTZ;
import java.text.ParseException; import java.text.ParseException;
import java.text.SimpleDateFormat; import java.text.SimpleDateFormat;
import java.util.Date; import java.util.Date;
import java.util.Locale; import java.util.Locale;
import java.util.SimpleTimeZone; import java.util.SimpleTimeZone;
import java.util.regex.Pattern;
import javax.annotation.Resource;
import org.jclouds.date.DateService; import org.jclouds.date.DateService;
import org.jclouds.logging.Logger;
/** /**
* *
@ -39,8 +37,6 @@ import org.jclouds.logging.Logger;
*/ */
public class SimpleDateFormatDateService implements DateService { public class SimpleDateFormatDateService implements DateService {
@Resource
protected Logger logger = Logger.NULL;
/* /*
* Use default Java Date/SimpleDateFormat classes for date manipulation, but be *very* careful to * Use default Java Date/SimpleDateFormat classes for date manipulation, but be *very* careful to
* guard against the lack of thread safety. * guard against the lack of thread safety.
@ -50,16 +46,16 @@ public class SimpleDateFormatDateService implements DateService {
"yyyy-MM-dd'T'HH:mm:ss'Z'", Locale.US); "yyyy-MM-dd'T'HH:mm:ss'Z'", Locale.US);
// @GuardedBy("this") // @GuardedBy("this")
private static final SimpleDateFormat iso8601SimpleDateFormat = new SimpleDateFormat( private static final SimpleDateFormat iso8601SimpleDateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'",
"yyyy-MM-dd'T'HH:mm:ss.SSS'Z'", Locale.US); Locale.US);
// @GuardedBy("this") // @GuardedBy("this")
private static final SimpleDateFormat rfc822SimpleDateFormat = new SimpleDateFormat( private static final SimpleDateFormat rfc822SimpleDateFormat = new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss z",
"EEE, dd MMM yyyy HH:mm:ss z", Locale.US); Locale.US);
// @GuardedBy("this") // @GuardedBy("this")
private static final SimpleDateFormat cSimpleDateFormat = new SimpleDateFormat( private static final SimpleDateFormat cSimpleDateFormat = new SimpleDateFormat("EEE MMM dd HH:mm:ss '+0000' yyyy",
"EEE MMM dd HH:mm:ss '+0000' yyyy", Locale.US); Locale.US);
static { static {
iso8601SimpleDateFormat.setTimeZone(new SimpleTimeZone(0, "GMT")); iso8601SimpleDateFormat.setTimeZone(new SimpleTimeZone(0, "GMT"));
@ -138,29 +134,6 @@ public class SimpleDateFormatDateService implements DateService {
} }
} }
public static final Pattern NANOS_TO_MILLIS_PATTERN = Pattern
.compile(".*[0-9][0-9][0-9][0-9][0-9][0-9]");
public static final Pattern TZ_PATTERN = Pattern.compile(".*[+-][0-9][0-9]:?[0-9][0-9]");
private String trimNanosToMillis(String toParse) {
if (NANOS_TO_MILLIS_PATTERN.matcher(toParse).matches())
toParse = toParse.substring(0, toParse.length() - 3) + 'Z';
return toParse;
}
public static final Pattern SECOND_PATTERN = Pattern.compile(".*[0-2][0-9]:00");
private String trimTZ(String toParse) {
if (TZ_PATTERN.matcher(toParse).matches()) {
logger.trace("trimming tz from %s", toParse);
toParse = toParse.substring(0, toParse.length() - 6) + 'Z';
}
if (toParse.length() == 25 && SECOND_PATTERN.matcher(toParse).matches())
toParse = toParse.substring(0, toParse.length() - 6) + 'Z';
return toParse;
}
public final Date iso8601SecondsDateParse(String toParse) { public final Date iso8601SecondsDateParse(String toParse) {
toParse = trimTZ(toParse); toParse = trimTZ(toParse);
synchronized (iso8601SecondsSimpleDateFormat) { synchronized (iso8601SecondsSimpleDateFormat) {

View File

@ -95,6 +95,18 @@ cloudservers-us.propertiesbuilder=org.jclouds.rackspace.cloudservers.CloudServer
bluelock-vcdirector.contextbuilder=org.jclouds.vcloud.bluelock.BluelockVCloudDirectorContextBuilder bluelock-vcdirector.contextbuilder=org.jclouds.vcloud.bluelock.BluelockVCloudDirectorContextBuilder
bluelock-vcdirector.propertiesbuilder=org.jclouds.vcloud.bluelock.BluelockVCloudDirectorPropertiesBuilder bluelock-vcdirector.propertiesbuilder=org.jclouds.vcloud.bluelock.BluelockVCloudDirectorPropertiesBuilder
bluelock-vcdirector.contextbuilder=org.jclouds.vcloud.bluelock.BluelockVCloudDirectorContextBuilder
bluelock-vcdirector.propertiesbuilder=org.jclouds.vcloud.bluelock.BluelockVCloudDirectorPropertiesBuilder
bluelock-vcloud-vcenterprise.contextbuilder=org.jclouds.bluelock.vcloud.vcenterprise.BluelockVCloudEnterpriseContextBuilder
bluelock-vcloud-vcenterprise.propertiesbuilder=org.jclouds.bluelock.vcloud.vcenterprise.BluelockVCloudEnterprisePropertiesBuilder
bluelock-vcloud-zone01.contextbuilder=org.jclouds.bluelock.vcloud.zone01.BluelockVCloudZone01ContextBuilder
bluelock-vcloud-zone01.propertiesbuilder=org.jclouds.bluelock.vcloud.zone01.BluelockVCloudZone01PropertiesBuilder
stratogen-vcloud-mycloud.contextbuilder=org.jclouds.stratogen.vcloud.mycloud.StratoGenVCloudMyCloudContextBuilder
stratogen-vcloud-mycloud.propertiesbuilder=org.jclouds.stratogen.vcloud.mycloud.StratoGenVCloudMyCloudPropertiesBuilder
gogrid.propertiesbuilder=org.jclouds.gogrid.GoGridPropertiesBuilder gogrid.propertiesbuilder=org.jclouds.gogrid.GoGridPropertiesBuilder
gogrid.contextbuilder=org.jclouds.gogrid.GoGridContextBuilder gogrid.contextbuilder=org.jclouds.gogrid.GoGridContextBuilder

View File

@ -79,7 +79,8 @@ public class DateServiceTest extends PerformanceTest {
} }
public DateServiceTest() { public DateServiceTest() {
// Constant time test values, each TestData item must contain matching times! // Constant time test values, each TestData item must contain matching
// times!
testData = new TestData[] { testData = new TestData[] {
new TestData("2009-03-12T02:00:07.000Z", "2009-03-12T02:00:07-04:00", "2009-03-12T02:00:07Z", new TestData("2009-03-12T02:00:07.000Z", "2009-03-12T02:00:07-04:00", "2009-03-12T02:00:07Z",
"Thu, 12 Mar 2009 02:00:07 GMT", "Thu Mar 12 02:00:07 +0000 2009", new Date(1236823207000l)), "Thu, 12 Mar 2009 02:00:07 GMT", "Thu Mar 12 02:00:07 +0000 2009", new Date(1236823207000l)),
@ -162,6 +163,12 @@ public class DateServiceTest extends PerformanceTest {
assertEquals(dateService.rfc822DateFormat(date), "Sat, 26 Sep 2009 23:37:05 GMT"); assertEquals(dateService.rfc822DateFormat(date), "Sat, 26 Sep 2009 23:37:05 GMT");
} }
@Test
void testTzWithExtraZ() throws ExecutionException, InterruptedException {
assertEquals(dateService.iso8601SecondsDateParse("2011-05-26T06:14:13-04:00").getTime(), 1306390453000l);
assertEquals(dateService.iso8601SecondsDateParse("2011-05-26T06:14:13-04:00Z").getTime(), 1306390453000l);
}
@Test @Test
void testRfc822DateFormatResponseTime() throws ExecutionException, InterruptedException { void testRfc822DateFormatResponseTime() throws ExecutionException, InterruptedException {
for (int i = 0; i < LOOP_COUNT; i++) for (int i = 0; i < LOOP_COUNT; i++)

View File

@ -59,15 +59,21 @@ public abstract class BaseHttpErrorHandlerTest {
protected abstract Class<? extends HttpErrorHandler> getHandlerClass(); protected abstract Class<? extends HttpErrorHandler> getHandlerClass();
protected void assertCodeMakes(String method, URI uri, int statusCode, String message, protected void assertCodeMakes(String method, URI uri, int statusCode, String message, String content,
Class<? extends Exception> expected) {
assertCodeMakes(method, uri, statusCode, message, null, content, expected);
}
protected void assertCodeMakes(String method, URI uri, int statusCode, String message, String contentType,
String content, Class<? extends Exception> expected) { String content, Class<? extends Exception> expected) {
HttpErrorHandler function = Guice.createInjector(new SaxParserModule()).getInstance( HttpErrorHandler function = Guice.createInjector(new SaxParserModule()).getInstance(getHandlerClass());
getHandlerClass());
HttpCommand command = createMock(HttpCommand.class); HttpCommand command = createMock(HttpCommand.class);
HttpRequest request = new HttpRequest(method, uri); HttpRequest request = new HttpRequest(method, uri);
HttpResponse response = new HttpResponse(statusCode, message, Payloads.newStringPayload(content)); HttpResponse response = new HttpResponse(statusCode, message, Payloads.newStringPayload(content));
if (contentType != null)
response.getPayload().getContentMetadata().setContentType(contentType);
expect(command.getCurrentRequest()).andReturn(request).atLeastOnce(); expect(command.getCurrentRequest()).andReturn(request).atLeastOnce();
command.setException(classEq(expected)); command.setException(classEq(expected));

View File

@ -1,313 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
Copyright (C) 2010 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.
====================================================================
-->
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.jclouds</groupId>
<artifactId>jclouds-demos-project</artifactId>
<version>1.0-SNAPSHOT</version>
</parent>
<artifactId>jclouds-demo-gae-tweetstore</artifactId>
<packaging>war</packaging>
<name>JClouds TweetStore for Google App Engine</name>
<description>JClouds TweetStore for Google App Engine using Guice for Dependency Injection</description>
<properties>
<!--
note you must set the property ${appengine.sdk.root} to a valid
extraction of appengine-java-sdk
-->
<appengine.applicationid>jclouds-tweetstore</appengine.applicationid>
<appengine.sdk.version>1.4.2</appengine.sdk.version>
<devappserver.address>localhost</devappserver.address>
<devappserver.port>8088</devappserver.port>
<jclouds.tweetstore.blobstores>cloudfiles-us,aws-s3,azureblob</jclouds.tweetstore.blobstores>
<jclouds.tweetstore.container>jclouds-tweetstore</jclouds.tweetstore.container>
</properties>
<dependencies>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>jclouds-blobstore</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.twitter4j</groupId>
<artifactId>twitter4j-core</artifactId>
<version>[2.1,)</version>
</dependency>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>jclouds-blobstore</artifactId>
<version>${project.version}</version>
<type>test-jar</type>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.jclouds.provider</groupId>
<artifactId>aws-s3</artifactId>
<version>${project.version}</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.jclouds.provider</groupId>
<artifactId>cloudfiles-us</artifactId>
<version>${project.version}</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.jclouds.provider</groupId>
<artifactId>azureblob</artifactId>
<version>${project.version}</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.jclouds.driver</groupId>
<artifactId>jclouds-gae</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>com.google.inject.extensions</groupId>
<artifactId>guice-servlet</artifactId>
<version>3.0</version>
</dependency>
<dependency>
<groupId>displaytag</groupId>
<artifactId>displaytag</artifactId>
<version>1.2</version>
<scope>runtime</scope>
<exclusions>
<exclusion>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-jdk14</artifactId>
<version>1.5.6</version>
<scope>runtime</scope>
</dependency>
<dependency>
<artifactId>jstl</artifactId>
<groupId>javax.servlet</groupId>
<version>1.1.2</version>
<scope>runtime</scope>
</dependency>
<dependency>
<artifactId>standard</artifactId>
<groupId>taglibs</groupId>
<version>1.1.2</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<version>2.5</version>
<scope>provided</scope>
</dependency>
<!-- Google App Engine API -->
<dependency>
<groupId>com.google.appengine</groupId>
<artifactId>appengine-api-1.0-sdk</artifactId>
<version>${appengine.sdk.version}</version>
</dependency>
<dependency>
<groupId>com.google.appengine</groupId>
<artifactId>appengine-tools-sdk</artifactId>
<version>${appengine.sdk.version}</version>
<scope>test</scope>
</dependency>
<!-- Needed..??> -->
<!-- Google App Engine Runtime Dependencies -->
<!--dependency>
<groupId>org.apache.geronimo.specs</groupId>
<artifactId>geronimo-jta_1.1_spec</artifactId>
<version>1.1.1</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.apache.geronimo.specs</groupId>
<artifactId>geronimo-jpa_3.0_spec</artifactId>
<version>1.1.1</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>com.google.appengine.orm</groupId>
<artifactId>jdo2-api</artifactId>
<version>2.3-eb</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.datanucleus</groupId>
<artifactId>datanucleus-core</artifactId>
<version>1.1.5</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>com.google.appengine.orm</groupId>
<artifactId>datanucleus-appengine</artifactId>
<version>1.0.8</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.datanucleus</groupId>
<artifactId>datanucleus-jpa</artifactId>
<version>1.1.5</version>
<scope>runtime</scope>
</dependency-->
</dependencies>
<build>
<finalName>${project.artifactId}</finalName>
<plugins>
<plugin>
<artifactId>maven-war-plugin</artifactId>
<configuration>
<webResources>
<resource>
<directory>src/main/appengine</directory>
<targetPath>WEB-INF/</targetPath>
<filtering>true</filtering>
</resource>
</webResources>
</configuration>
</plugin>
<plugin>
<artifactId>maven-surefire-plugin</artifactId>
<executions>
<execution>
<id>integration</id>
<phase>integration-test</phase>
<goals>
<goal>test</goal>
</goals>
<configuration>
<systemProperties>
<property>
<name>appengine.sdk.root</name>
<value>${appengine.sdk.root}</value>
</property>
<property>
<name>devappserver.address</name>
<value>${devappserver.address}</value>
</property>
<property>
<name>devappserver.port</name>
<value>${devappserver.port}</value>
</property>
<property>
<name>warfile</name>
<value>${project.build.directory}/${project.artifactId}</value>
</property>
</systemProperties>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
<profiles>
<profile>
<id>live</id>
<build>
<plugins>
<plugin>
<artifactId>maven-surefire-plugin</artifactId>
<executions>
<execution>
<id>integration</id>
<phase>integration-test</phase>
<goals>
<goal>test</goal>
</goals>
<configuration>
<systemProperties>
<property>
<name>test.twitter.identity</name>
<value>${test.twitter.identity}</value>
</property>
<property>
<name>test.twitter.credential</name>
<value>${test.twitter.credential}</value>
</property>
<property>
<name>test.azureblob.identity</name>
<value>${test.azureblob.identity}</value>
</property>
<property>
<name>test.azureblob.credential</name>
<value>${test.azureblob.credential}</value>
</property>
<property>
<name>test.cloudfiles-us.identity</name>
<value>${test.cloudfiles-us.identity}</value>
</property>
<property>
<name>test.cloudfiles-us.credential</name>
<value>${test.cloudfiles-us.credential}</value>
</property>
<property>
<name>test.aws-s3.identity</name>
<value>${test.aws-s3.identity}</value>
</property>
<property>
<name>test.aws-s3.credential</name>
<value>${test.aws-s3.credential}</value>
</property>
<property>
<name>appengine.sdk.root</name>
<value>${appengine.sdk.root}</value>
</property>
<property>
<name>devappserver.address</name>
<value>${devappserver.address}</value>
</property>
<property>
<name>devappserver.port</name>
<value>${devappserver.port}</value>
</property>
<property>
<name>jclouds.tweetstore.blobstores</name>
<value>${jclouds.tweetstore.blobstores}</value>
</property>
<property>
<name>jclouds.tweetstore.container</name>
<value>${jclouds.tweetstore.container}</value>
</property>
<property>
<name>warfile</name>
<value>${project.build.directory}/${project.artifactId}</value>
</property>
</systemProperties>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</profile>
</profiles>
</project>

View File

@ -32,15 +32,13 @@
<packaging>pom</packaging> <packaging>pom</packaging>
<name>jclouds demos project</name> <name>jclouds demos project</name>
<modules> <modules>
<module>gae-tweetstore</module>
<module>gae-tweetstore-spring</module>
<module>getpath</module> <module>getpath</module>
<module>googleappengine</module> <module>googleappengine</module>
<module>perftest</module> <module>perftest</module>
<module>runatcloud-tweetstore</module>
<module>speedtest-azurequeue</module> <module>speedtest-azurequeue</module>
<module>speedtest-sqs</module> <module>speedtest-sqs</module>
<module>simpledb</module> <module>simpledb</module>
<module>tweetstore</module>
</modules> </modules>
<dependencies> <dependencies>
<dependency> <dependency>

View File

@ -25,6 +25,8 @@ It should not be regarded as a sample of how to write a web application using Sp
however! The original jclouds-demo-gae-tweetstore has been modified in as few places as however! The original jclouds-demo-gae-tweetstore has been modified in as few places as
possible; it has not been rewritten in the style of a Spring MVC application. possible; it has not been rewritten in the style of a Spring MVC application.
A guide to generating Twitter consumer keys and access tokens is at http://tinyurl.com/2fhebgb
This sample uses the Google App Engine for Java SDK located at This sample uses the Google App Engine for Java SDK located at
http://code.google.com/p/googleappengine/downloads/list http://code.google.com/p/googleappengine/downloads/list
@ -48,13 +50,15 @@ attempting to run 'mvn -Plive install'
<activeByDefault>true</activeByDefault> <activeByDefault>true</activeByDefault>
</activation> </activation>
<properties> <properties>
<jclouds.aws-s3.identity>YOUR_ACCESS_KEY_ID</jclouds.aws-s3.identity> <test.aws-s3.identity>YOUR_ACCESS_KEY_ID</test.aws-s3.identity>
<jclouds.aws-s3.credential>YOUR_SECRET_KEY</jclouds.aws-s3.credential> <test.aws-s3.credential>YOUR_SECRET_KEY</test.aws-s3.credential>
<jclouds.cloudfiles-us.identity>YOUR_USER</jclouds.cloudfiles-us.identity> <test.cloudfiles-us.identity>YOUR_USER</test.cloudfiles-us.identity>
<jclouds.cloudfiles-us.credential>YOUR_HEX_KEY</jclouds.cloudfiles-us.credential> <test.cloudfiles-us.credential>YOUR_HEX_KEY</test.cloudfiles-us.credential>
<jclouds.azureblob.identity>YOUR_ACCOUNT</jclouds.azureblob.identity> <test.azureblob.identity>YOUR_ACCOUNT</test.azureblob.identity>
<jclouds.azureblob.credential>YOUR_BASE64_ENCODED_KEY</jclouds.azureblob.credential> <test.azureblob.credential>YOUR_BASE64_ENCODED_KEY</test.azureblob.credential>
<jclouds.twitter.identity>YOUR_TWITTER_USERNAME</jclouds.twitter.identity> <test.twitter.gae-tweetstore-spring.consumer.identity>YOUR_TWITTER_CONSUMER_KEY</test.twitter.gae-tweetstore-spring.consumer.identity>
<jclouds.twitter.credential>YOUR_TWITTER_PASSWORD</jclouds.twitter.credential> <test.twitter.gae-tweetstore-spring.consumer.credential>YOUR_TWITTER_CONSUMER_SECRET</test.twitter.gae-tweetstore-spring.consumer.credential>
<test.twitter.gae-tweetstore-spring.access.identity>YOUR_TWITTER_ACCESSTOKEN</test.twitter.gae-tweetstore-spring.access.identity>
<test.twitter.gae-tweetstore-spring.access.credential>YOUR_TWITTER_ACCESSTOKEN_SECRET</test.twitter.gae-tweetstore-spring.access.credential>
</properties> </properties>
</profile> </profile>

View File

@ -24,7 +24,7 @@
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
<parent> <parent>
<groupId>org.jclouds</groupId> <groupId>org.jclouds</groupId>
<artifactId>jclouds-demos-project</artifactId> <artifactId>jclouds-demos-tweetstore-project</artifactId>
<version>1.0-SNAPSHOT</version> <version>1.0-SNAPSHOT</version>
</parent> </parent>
<artifactId>jclouds-demo-gae-tweetstore-spring</artifactId> <artifactId>jclouds-demo-gae-tweetstore-spring</artifactId>
@ -41,46 +41,10 @@
<appengine.sdk.version>1.4.2</appengine.sdk.version> <appengine.sdk.version>1.4.2</appengine.sdk.version>
<devappserver.address>localhost</devappserver.address> <devappserver.address>localhost</devappserver.address>
<devappserver.port>8088</devappserver.port> <devappserver.port>8088</devappserver.port>
<jclouds.tweetstore.blobstores>cloudfiles-us,aws-s3,azureblob</jclouds.tweetstore.blobstores>
<jclouds.tweetstore.container>jclouds-tweetstore-spring</jclouds.tweetstore.container> <jclouds.tweetstore.container>jclouds-tweetstore-spring</jclouds.tweetstore.container>
</properties> </properties>
<dependencies> <dependencies>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>jclouds-blobstore</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.twitter4j</groupId>
<artifactId>twitter4j-core</artifactId>
<version>[2.1,)</version>
</dependency>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>jclouds-blobstore</artifactId>
<version>${project.version}</version>
<type>test-jar</type>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.jclouds.provider</groupId>
<artifactId>aws-s3</artifactId>
<version>${project.version}</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.jclouds.provider</groupId>
<artifactId>cloudfiles-us</artifactId>
<version>${project.version}</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.jclouds.provider</groupId>
<artifactId>azureblob</artifactId>
<version>${project.version}</version>
<scope>runtime</scope>
</dependency>
<dependency> <dependency>
<groupId>org.jclouds.driver</groupId> <groupId>org.jclouds.driver</groupId>
<artifactId>jclouds-gae</artifactId> <artifactId>jclouds-gae</artifactId>
@ -102,42 +66,6 @@
<version>2.2</version> <version>2.2</version>
<scope>runtime</scope> <scope>runtime</scope>
</dependency> </dependency>
<dependency>
<groupId>displaytag</groupId>
<artifactId>displaytag</artifactId>
<version>1.2</version>
<scope>runtime</scope>
<exclusions>
<exclusion>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-jdk14</artifactId>
<version>1.5.6</version>
<scope>runtime</scope>
</dependency>
<dependency>
<artifactId>standard</artifactId>
<groupId>taglibs</groupId>
<version>1.1.2</version>
<scope>runtime</scope>
</dependency>
<dependency>
<artifactId>jstl</artifactId>
<groupId>javax.servlet</groupId>
<version>1.1.2</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<version>2.5</version>
<scope>provided</scope>
</dependency>
<!-- Google App Engine API --> <!-- Google App Engine API -->
<dependency> <dependency>
@ -152,21 +80,9 @@
<scope>test</scope> <scope>test</scope>
</dependency> </dependency>
</dependencies> </dependencies>
<build> <build>
<finalName>${project.artifactId}</finalName>
<plugins> <plugins>
<plugin>
<artifactId>maven-war-plugin</artifactId>
<configuration>
<webResources>
<resource>
<directory>src/main/appengine</directory>
<targetPath>WEB-INF/</targetPath>
<filtering>true</filtering>
</resource>
</webResources>
</configuration>
</plugin>
<plugin> <plugin>
<artifactId>maven-surefire-plugin</artifactId> <artifactId>maven-surefire-plugin</artifactId>
<executions> <executions>
@ -219,12 +135,20 @@
<configuration> <configuration>
<systemProperties> <systemProperties>
<property> <property>
<name>test.twitter.identity</name> <name>test.twitter.consumer.identity</name>
<value>${test.twitter.identity}</value> <value>${test.twitter.gae-tweetstore-spring.consumer.identity}</value>
</property> </property>
<property> <property>
<name>test.twitter.credential</name> <name>test.twitter.consumer.credential</name>
<value>${test.twitter.credential}</value> <value>${test.twitter.gae-tweetstore-spring.consumer.credential}</value>
</property>
<property>
<name>test.twitter.access.identity</name>
<value>${test.twitter.gae-tweetstore-spring.access.identity}</value>
</property>
<property>
<name>test.twitter.access.credential</name>
<value>${test.twitter.gae-tweetstore-spring.access.credential}</value>
</property> </property>
<property> <property>
<name>test.azureblob.identity</name> <name>test.azureblob.identity</name>
@ -282,5 +206,22 @@
</plugins> </plugins>
</build> </build>
</profile> </profile>
<profile>
<id>deploy</id>
<build>
<plugins>
<plugin>
<groupId>net.kindleit</groupId>
<artifactId>maven-gae-plugin</artifactId>
<version>0.8.4</version>
<configuration>
<serverId>google-appengine</serverId>
<sdkDir>${appengine.sdk.root}</sdkDir>
</configuration>
</plugin>
</plugins>
</build>
</profile>
</profiles> </profiles>
</project> </project>

View File

@ -55,7 +55,6 @@ import twitter4j.conf.ConfigurationBuilder;
import com.google.appengine.api.taskqueue.Queue; import com.google.appengine.api.taskqueue.Queue;
import com.google.appengine.api.taskqueue.QueueFactory; import com.google.appengine.api.taskqueue.QueueFactory;
import com.google.appengine.api.taskqueue.TaskOptions.Builder;
import com.google.appengine.api.taskqueue.TaskOptions.Method; import com.google.appengine.api.taskqueue.TaskOptions.Method;
import com.google.common.base.Splitter; import com.google.common.base.Splitter;
import com.google.common.collect.ImmutableSet; import com.google.common.collect.ImmutableSet;

View File

@ -24,10 +24,11 @@ package org.jclouds.demo.tweetstore.reference;
* @author Adrian Cole * @author Adrian Cole
*/ */
public interface TweetStoreConstants { public interface TweetStoreConstants {
public static final String PROPERTY_TWEETSTORE_CONTAINER = "jclouds.tweetstore.container"; static final String PROPERTY_TWEETSTORE_BLOBSTORES = "jclouds.tweetstore.blobstores";
static final String PROPERTY_TWEETSTORE_CONTAINER = "jclouds.tweetstore.container";
/** /**
* Note that this has to conform to restrictions of all blobstores. for example, azure doesn't * Note that this has to conform to restrictions of all blobstores. for
* support periods. * example, azure doesn't support periods.
*/ */
public static final String SENDER_NAME = "sendername"; static final String SENDER_NAME = "sendername";
} }

View File

@ -19,6 +19,7 @@
package org.jclouds.demo.tweetstore.integration; package org.jclouds.demo.tweetstore.integration;
import static com.google.common.base.Preconditions.checkNotNull; import static com.google.common.base.Preconditions.checkNotNull;
import static org.jclouds.demo.tweetstore.reference.TweetStoreConstants.PROPERTY_TWEETSTORE_BLOBSTORES;
import static org.jclouds.demo.tweetstore.reference.TweetStoreConstants.PROPERTY_TWEETSTORE_CONTAINER; import static org.jclouds.demo.tweetstore.reference.TweetStoreConstants.PROPERTY_TWEETSTORE_CONTAINER;
import java.io.IOException; import java.io.IOException;
@ -71,14 +72,14 @@ public class TweetStoreLiveTest {
private String container; private String container;
private static final Iterable<String> blobstores = private static final Iterable<String> blobstores =
Splitter.on(',').split(System.getProperty("jclouds.tweetstore.blobstores", Splitter.on(',').split(System.getProperty(PROPERTY_TWEETSTORE_BLOBSTORES,
"cloudfiles-us,aws-s3,azureblob")); "cloudfiles-us,aws-s3,azureblob"));
private static final Properties props = new Properties(); private static final Properties props = new Properties();
@BeforeTest @BeforeTest
void clearAndCreateContainers() throws InterruptedException, ExecutionException, TimeoutException, IOException, void clearAndCreateContainers() throws InterruptedException, ExecutionException, TimeoutException, IOException,
TwitterException { TwitterException {
container = checkNotNull(System.getProperty(PROPERTY_TWEETSTORE_CONTAINER), PROPERTY_TWEETSTORE_CONTAINER); container = getRequiredSystemProperty(PROPERTY_TWEETSTORE_CONTAINER);
props.setProperty(PROPERTY_TWEETSTORE_CONTAINER, container); props.setProperty(PROPERTY_TWEETSTORE_CONTAINER, container);
props.setProperty(SpringServletConfig.PROPERTY_BLOBSTORE_CONTEXTS, Joiner.on(',').join(blobstores)); props.setProperty(SpringServletConfig.PROPERTY_BLOBSTORE_CONTEXTS, Joiner.on(',').join(blobstores));
@ -98,10 +99,13 @@ public class TweetStoreLiveTest {
contexts.put(provider, factory.createContext(provider, wiring, props)); contexts.put(provider, factory.createContext(provider, wiring, props));
} }
Configuration twitterConf = new ConfigurationBuilder() Configuration conf = new ConfigurationBuilder()
.setUser(props.getProperty("twitter.identity")) .setOAuthConsumerKey(props.getProperty(TwitterConstants.PROPERTY_TWITTER_CONSUMER_KEY))
.setPassword(props.getProperty("twitter.credential")).build(); .setOAuthConsumerSecret(props.getProperty(TwitterConstants.PROPERTY_TWITTER_CONSUMER_SECRET))
Twitter client = new TwitterFactory(twitterConf).getInstance(); .setOAuthAccessToken(props.getProperty(TwitterConstants.PROPERTY_TWITTER_ACCESSTOKEN))
.setOAuthAccessTokenSecret(props.getProperty(TwitterConstants.PROPERTY_TWITTER_ACCESSTOKEN_SECRET))
.build();
Twitter client = new TwitterFactory(conf).getInstance();
StoreTweetsController controller = new StoreTweetsController(contexts, container, client); StoreTweetsController controller = new StoreTweetsController(contexts, container, client);
ResponseList<Status> statuses = client.getMentions(); ResponseList<Status> statuses = client.getMentions();
@ -135,19 +139,27 @@ public class TweetStoreLiveTest {
} }
} }
private static String getRequiredSystemProperty(String key) {
return checkNotNull(System.getProperty(key), key);
}
private void addConfigurationForTwitter(Properties props) { private void addConfigurationForTwitter(Properties props) {
props.setProperty("twitter.identity", props.setProperty(TwitterConstants.PROPERTY_TWITTER_CONSUMER_KEY,
checkNotNull(System.getProperty("test.twitter.identity"), "test.twitter.identity")); getRequiredSystemProperty("test." + TwitterConstants.PROPERTY_TWITTER_CONSUMER_KEY));
props.setProperty("twitter.credential", props.setProperty(TwitterConstants.PROPERTY_TWITTER_CONSUMER_SECRET,
checkNotNull(System.getProperty("test.twitter.credential"), "test.twitter.credential")); getRequiredSystemProperty("test." + TwitterConstants.PROPERTY_TWITTER_CONSUMER_SECRET));
props.setProperty(TwitterConstants.PROPERTY_TWITTER_ACCESSTOKEN,
getRequiredSystemProperty("test." + TwitterConstants.PROPERTY_TWITTER_ACCESSTOKEN));
props.setProperty(TwitterConstants.PROPERTY_TWITTER_ACCESSTOKEN_SECRET,
getRequiredSystemProperty("test." + TwitterConstants.PROPERTY_TWITTER_ACCESSTOKEN_SECRET));
} }
private void addCredentialsForBlobStores(Properties props) { private void addCredentialsForBlobStores(Properties props) {
for (String provider : blobstores) { for (String provider : blobstores) {
props.setProperty(provider + ".identity", props.setProperty(provider + ".identity",
checkNotNull(System.getProperty("test." + provider + ".identity"), "test." + provider + ".identity")); getRequiredSystemProperty("test." + provider + ".identity"));
props.setProperty(provider + ".credential", props.setProperty(provider + ".credential",
checkNotNull(System.getProperty("test." + provider + ".credential"), "test." + provider + ".credential")); getRequiredSystemProperty("test." + provider + ".credential"));
} }
} }
@ -208,4 +220,11 @@ public class TweetStoreLiveTest {
String string = Strings2.toStringAndClose(i); String string = Strings2.toStringAndClose(i);
assert string.indexOf("Tweets in Clouds") >= 0 : string; assert string.indexOf("Tweets in Clouds") >= 0 : string;
} }
private static interface TwitterConstants {
static final String PROPERTY_TWITTER_CONSUMER_KEY = "twitter.consumer.identity";
static final String PROPERTY_TWITTER_CONSUMER_SECRET = "twitter.consumer.credential";
static final String PROPERTY_TWITTER_ACCESSTOKEN = "twitter.access.identity";
static final String PROPERTY_TWITTER_ACCESSTOKEN_SECRET = "twitter.access.credential";
}
} }

View File

@ -17,6 +17,8 @@
==================================================================== ====================================================================
==== ====
A guide to generating Twitter consumer keys and access tokens is at http://tinyurl.com/2fhebgb
This sample uses the Google App Engine for Java SDK located at This sample uses the Google App Engine for Java SDK located at
http://code.google.com/p/googleappengine/downloads/list http://code.google.com/p/googleappengine/downloads/list
@ -40,13 +42,15 @@ attempting to run 'mvn -Plive install'
<activeByDefault>true</activeByDefault> <activeByDefault>true</activeByDefault>
</activation> </activation>
<properties> <properties>
<jclouds.aws-s3.identity>YOUR_ACCESS_KEY_ID</jclouds.aws-s3.identity> <test.aws-s3.identity>YOUR_ACCESS_KEY_ID</test.aws-s3.identity>
<jclouds.aws-s3.credential>YOUR_SECRET_KEY</jclouds.aws-s3.credential> <test.aws-s3.credential>YOUR_SECRET_KEY</test.aws-s3.credential>
<jclouds.cloudfiles-us.identity>YOUR_USER</jclouds.cloudfiles-us.identity> <test.cloudfiles-us.identity>YOUR_USER</test.cloudfiles-us.identity>
<jclouds.cloudfiles-us.credential>YOUR_HEX_KEY</jclouds.cloudfiles-us.credential> <test.cloudfiles-us.credential>YOUR_HEX_KEY</test.cloudfiles-us.credential>
<jclouds.azureblob.identity>YOUR_ACCOUNT</jclouds.azureblob.identity> <test.azureblob.identity>YOUR_ACCOUNT</test.azureblob.identity>
<jclouds.azureblob.credential>YOUR_BASE64_ENCODED_KEY</jclouds.azureblob.credential> <test.azureblob.credential>YOUR_BASE64_ENCODED_KEY</test.azureblob.credential>
<jclouds.twitter.identity>YOUR_TWITTER_USERNAME</jclouds.twitter.identity> <test.twitter.gae-tweetstore.consumer.identity>YOUR_TWITTER_CONSUMER_KEY</test.twitter.gae-tweetstore.consumer.identity>
<jclouds.twitter.credential>YOUR_TWITTER_PASSWORD</jclouds.twitter.credential> <test.twitter.gae-tweetstore.consumer.credential>YOUR_TWITTER_CONSUMER_SECRET</test.twitter.gae-tweetstore.consumer.credential>
<test.twitter.gae-tweetstore.access.identity>YOUR_TWITTER_ACCESSTOKEN</test.twitter.gae-tweetstore.access.identity>
<test.twitter.gae-tweetstore.access.credential>YOUR_TWITTER_ACCESSTOKEN_SECRET</test.twitter.gae-tweetstore.access.credential>
</properties> </properties>
</profile> </profile>

View File

@ -0,0 +1,213 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
Copyright (C) 2010 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.
====================================================================
-->
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.jclouds</groupId>
<artifactId>jclouds-demos-tweetstore-project</artifactId>
<version>1.0-SNAPSHOT</version>
</parent>
<artifactId>jclouds-demo-gae-tweetstore</artifactId>
<packaging>war</packaging>
<name>JClouds TweetStore for Google App Engine</name>
<description>JClouds TweetStore for Google App Engine using Guice for Dependency Injection</description>
<properties>
<!--
note you must set the property ${appengine.sdk.root} to a valid
extraction of appengine-java-sdk
-->
<appengine.applicationid>jclouds-tweetstore</appengine.applicationid>
<appengine.sdk.version>1.4.2</appengine.sdk.version>
<devappserver.address>localhost</devappserver.address>
<devappserver.port>8088</devappserver.port>
<jclouds.tweetstore.container>jclouds-tweetstore</jclouds.tweetstore.container>
</properties>
<dependencies>
<dependency>
<groupId>org.jclouds.driver</groupId>
<artifactId>jclouds-gae</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>com.google.inject.extensions</groupId>
<artifactId>guice-servlet</artifactId>
<version>3.0</version>
</dependency>
<!-- Google App Engine API -->
<dependency>
<groupId>com.google.appengine</groupId>
<artifactId>appengine-api-1.0-sdk</artifactId>
<version>${appengine.sdk.version}</version>
</dependency>
<dependency>
<groupId>com.google.appengine</groupId>
<artifactId>appengine-tools-sdk</artifactId>
<version>${appengine.sdk.version}</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<artifactId>maven-surefire-plugin</artifactId>
<executions>
<execution>
<id>integration</id>
<phase>integration-test</phase>
<goals>
<goal>test</goal>
</goals>
<configuration>
<systemProperties>
<property>
<name>appengine.sdk.root</name>
<value>${appengine.sdk.root}</value>
</property>
<property>
<name>devappserver.address</name>
<value>${devappserver.address}</value>
</property>
<property>
<name>devappserver.port</name>
<value>${devappserver.port}</value>
</property>
<property>
<name>warfile</name>
<value>${project.build.directory}/${project.artifactId}</value>
</property>
</systemProperties>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
<profiles>
<profile>
<id>live</id>
<build>
<plugins>
<plugin>
<artifactId>maven-surefire-plugin</artifactId>
<executions>
<execution>
<id>integration</id>
<phase>integration-test</phase>
<goals>
<goal>test</goal>
</goals>
<configuration>
<systemProperties>
<property>
<name>test.twitter.consumer.identity</name>
<value>${test.twitter.gae-tweetstore.consumer.identity}</value>
</property>
<property>
<name>test.twitter.consumer.credential</name>
<value>${test.twitter.gae-tweetstore.consumer.credential}</value>
</property>
<property>
<name>test.twitter.access.identity</name>
<value>${test.twitter.gae-tweetstore.access.identity}</value>
</property>
<property>
<name>test.twitter.access.credential</name>
<value>${test.twitter.gae-tweetstore.access.credential}</value>
</property>
<property>
<name>test.azureblob.identity</name>
<value>${test.azureblob.identity}</value>
</property>
<property>
<name>test.azureblob.credential</name>
<value>${test.azureblob.credential}</value>
</property>
<property>
<name>test.cloudfiles-us.identity</name>
<value>${test.cloudfiles-us.identity}</value>
</property>
<property>
<name>test.cloudfiles-us.credential</name>
<value>${test.cloudfiles-us.credential}</value>
</property>
<property>
<name>test.aws-s3.identity</name>
<value>${test.aws-s3.identity}</value>
</property>
<property>
<name>test.aws-s3.credential</name>
<value>${test.aws-s3.credential}</value>
</property>
<property>
<name>appengine.sdk.root</name>
<value>${appengine.sdk.root}</value>
</property>
<property>
<name>devappserver.address</name>
<value>${devappserver.address}</value>
</property>
<property>
<name>devappserver.port</name>
<value>${devappserver.port}</value>
</property>
<property>
<name>jclouds.tweetstore.blobstores</name>
<value>${jclouds.tweetstore.blobstores}</value>
</property>
<property>
<name>jclouds.tweetstore.container</name>
<value>${jclouds.tweetstore.container}</value>
</property>
<property>
<name>warfile</name>
<value>${project.build.directory}/${project.artifactId}</value>
</property>
</systemProperties>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</profile>
<profile>
<id>deploy</id>
<build>
<plugins>
<plugin>
<groupId>net.kindleit</groupId>
<artifactId>maven-gae-plugin</artifactId>
<version>0.8.4</version>
<configuration>
<serverId>google-appengine</serverId>
<sdkDir>${appengine.sdk.root}</sdkDir>
</configuration>
</plugin>
</plugins>
</build>
</profile>
</profiles>
</project>

View File

@ -24,10 +24,11 @@ package org.jclouds.demo.tweetstore.reference;
* @author Adrian Cole * @author Adrian Cole
*/ */
public interface TweetStoreConstants { public interface TweetStoreConstants {
public static final String PROPERTY_TWEETSTORE_CONTAINER = "jclouds.tweetstore.container"; static final String PROPERTY_TWEETSTORE_BLOBSTORES = "jclouds.tweetstore.blobstores";
static final String PROPERTY_TWEETSTORE_CONTAINER = "jclouds.tweetstore.container";
/** /**
* Note that this has to conform to restrictions of all blobstores. for example, azure doesn't * Note that this has to conform to restrictions of all blobstores. for example, azure doesn't
* support periods. * support periods.
*/ */
public static final String SENDER_NAME = "sendername"; static final String SENDER_NAME = "sendername";
} }

View File

@ -19,6 +19,7 @@
package org.jclouds.demo.tweetstore.integration; package org.jclouds.demo.tweetstore.integration;
import static com.google.common.base.Preconditions.checkNotNull; import static com.google.common.base.Preconditions.checkNotNull;
import static org.jclouds.demo.tweetstore.reference.TweetStoreConstants.PROPERTY_TWEETSTORE_BLOBSTORES;
import static org.jclouds.demo.tweetstore.reference.TweetStoreConstants.PROPERTY_TWEETSTORE_CONTAINER; import static org.jclouds.demo.tweetstore.reference.TweetStoreConstants.PROPERTY_TWEETSTORE_CONTAINER;
import java.io.IOException; import java.io.IOException;
@ -70,15 +71,14 @@ public class TweetStoreLiveTest {
private Map<String, BlobStoreContext> contexts; private Map<String, BlobStoreContext> contexts;
private String container; private String container;
private static final Iterable<String> blobstores = private static final Iterable<String> blobstores =
Splitter.on(',').split(System.getProperty("jclouds.tweetstore.blobstores", Splitter.on(',').split(System.getProperty(PROPERTY_TWEETSTORE_BLOBSTORES,
"cloudfiles-us,aws-s3,azureblob")); "cloudfiles-us,aws-s3,azureblob"));
private static final Properties props = new Properties(); private static final Properties props = new Properties();
@BeforeTest @BeforeTest
void clearAndCreateContainers() throws InterruptedException, ExecutionException, TimeoutException, IOException, void clearAndCreateContainers() throws InterruptedException, ExecutionException, TimeoutException, IOException,
TwitterException { TwitterException {
container = checkNotNull(System.getProperty(PROPERTY_TWEETSTORE_CONTAINER), container = getRequiredSystemProperty(PROPERTY_TWEETSTORE_CONTAINER);
PROPERTY_TWEETSTORE_CONTAINER);
props.setProperty(PROPERTY_TWEETSTORE_CONTAINER, container); props.setProperty(PROPERTY_TWEETSTORE_CONTAINER, container);
props.setProperty(GuiceServletConfig.PROPERTY_BLOBSTORE_CONTEXTS, Joiner.on(',').join(blobstores)); props.setProperty(GuiceServletConfig.PROPERTY_BLOBSTORE_CONTEXTS, Joiner.on(',').join(blobstores));
@ -99,8 +99,11 @@ public class TweetStoreLiveTest {
} }
Configuration conf = new ConfigurationBuilder() Configuration conf = new ConfigurationBuilder()
.setUser(props.getProperty("twitter.identity")) .setOAuthConsumerKey(props.getProperty(TwitterConstants.PROPERTY_TWITTER_CONSUMER_KEY))
.setPassword(props.getProperty("twitter.credential")).build(); .setOAuthConsumerSecret(props.getProperty(TwitterConstants.PROPERTY_TWITTER_CONSUMER_SECRET))
.setOAuthAccessToken(props.getProperty(TwitterConstants.PROPERTY_TWITTER_ACCESSTOKEN))
.setOAuthAccessTokenSecret(props.getProperty(TwitterConstants.PROPERTY_TWITTER_ACCESSTOKEN_SECRET))
.build();
Twitter client = new TwitterFactory(conf).getInstance(); Twitter client = new TwitterFactory(conf).getInstance();
StoreTweetsController controller = new StoreTweetsController(contexts, container, client); StoreTweetsController controller = new StoreTweetsController(contexts, container, client);
@ -140,6 +143,30 @@ public class TweetStoreLiveTest {
} }
} }
private static String getRequiredSystemProperty(String key) {
return checkNotNull(System.getProperty(key), key);
}
private void addConfigurationForTwitter(Properties props) {
props.setProperty(TwitterConstants.PROPERTY_TWITTER_CONSUMER_KEY,
getRequiredSystemProperty("test." + TwitterConstants.PROPERTY_TWITTER_CONSUMER_KEY));
props.setProperty(TwitterConstants.PROPERTY_TWITTER_CONSUMER_SECRET,
getRequiredSystemProperty("test." + TwitterConstants.PROPERTY_TWITTER_CONSUMER_SECRET));
props.setProperty(TwitterConstants.PROPERTY_TWITTER_ACCESSTOKEN,
getRequiredSystemProperty("test." + TwitterConstants.PROPERTY_TWITTER_ACCESSTOKEN));
props.setProperty(TwitterConstants.PROPERTY_TWITTER_ACCESSTOKEN_SECRET,
getRequiredSystemProperty("test." + TwitterConstants.PROPERTY_TWITTER_ACCESSTOKEN_SECRET));
}
private void addCredentialsForBlobStores(Properties props) {
for (String provider : blobstores) {
props.setProperty(provider + ".identity",
getRequiredSystemProperty("test." + provider + ".identity"));
props.setProperty(provider + ".credential",
getRequiredSystemProperty("test." + provider + ".credential"));
}
}
@BeforeTest(dependsOnMethods = "clearAndCreateContainers") @BeforeTest(dependsOnMethods = "clearAndCreateContainers")
@Parameters({ "warfile", "devappserver.address", "devappserver.port" }) @Parameters({ "warfile", "devappserver.address", "devappserver.port" })
public void startDevAppServer(final String warfile, final String address, final String port) throws Exception { public void startDevAppServer(final String warfile, final String address, final String port) throws Exception {
@ -149,21 +176,6 @@ public class TweetStoreLiveTest {
server.writePropertiesAndStartServer(address, port, warfile, props); server.writePropertiesAndStartServer(address, port, warfile, props);
} }
private void addConfigurationForTwitter(Properties props) {
props.setProperty("twitter.identity", checkNotNull(System.getProperty("test.twitter.identity"), "test.twitter.identity"));
props.setProperty("twitter.credential",
checkNotNull(System.getProperty("test.twitter.credential"), "test.twitter.credential"));
}
private void addCredentialsForBlobStores(Properties props) {
for (String provider : blobstores) {
props.setProperty(provider + ".identity",
checkNotNull(System.getProperty("test." + provider + ".identity"), "test." + provider + ".identity"));
props.setProperty(provider + ".credential",
checkNotNull(System.getProperty("test." + provider + ".credential"), "test." + provider + ".credential"));
}
}
@Test @Test
public void shouldPass() throws InterruptedException, IOException { public void shouldPass() throws InterruptedException, IOException {
InputStream i = url.openStream(); InputStream i = url.openStream();
@ -213,4 +225,11 @@ public class TweetStoreLiveTest {
String string = Strings2.toStringAndClose(i); String string = Strings2.toStringAndClose(i);
assert string.indexOf("Tweets in Clouds") >= 0 : string; assert string.indexOf("Tweets in Clouds") >= 0 : string;
} }
private static interface TwitterConstants {
static final String PROPERTY_TWITTER_CONSUMER_KEY = "twitter.consumer.identity";
static final String PROPERTY_TWITTER_CONSUMER_SECRET = "twitter.consumer.credential";
static final String PROPERTY_TWITTER_ACCESSTOKEN = "twitter.access.identity";
static final String PROPERTY_TWITTER_ACCESSTOKEN_SECRET = "twitter.access.credential";
}
} }

207
demos/tweetstore/pom.xml Normal file
View File

@ -0,0 +1,207 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
Copyright (C) 2010 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.
====================================================================
-->
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<parent>
<artifactId>jclouds-demos-project</artifactId>
<groupId>org.jclouds</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>jclouds-demos-tweetstore-project</artifactId>
<packaging>pom</packaging>
<name>jclouds TweetStore demos project</name>
<modules>
<module>gae-tweetstore</module>
<module>gae-tweetstore-spring</module>
<module>runatcloud-tweetstore</module>
</modules>
<properties>
<remoteResourcesDirectory>target/maven-shared-archive-resources</remoteResourcesDirectory>
<jclouds.tweetstore.blobstores>cloudfiles-us,aws-s3,azureblob</jclouds.tweetstore.blobstores>
</properties>
<dependencies>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>jclouds-blobstore</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.twitter4j</groupId>
<artifactId>twitter4j-core</artifactId>
<version>[2.2,)</version>
</dependency>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>jclouds-blobstore</artifactId>
<version>${project.version}</version>
<type>test-jar</type>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.jclouds.provider</groupId>
<artifactId>aws-s3</artifactId>
<version>${project.version}</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.jclouds.provider</groupId>
<artifactId>cloudfiles-us</artifactId>
<version>${project.version}</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.jclouds.provider</groupId>
<artifactId>azureblob</artifactId>
<version>${project.version}</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>displaytag</groupId>
<artifactId>displaytag</artifactId>
<version>1.2</version>
<scope>runtime</scope>
<exclusions>
<exclusion>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-jdk14</artifactId>
<version>1.5.6</version>
<scope>runtime</scope>
</dependency>
<dependency>
<artifactId>jstl</artifactId>
<groupId>javax.servlet</groupId>
<version>1.1.2</version>
<scope>runtime</scope>
</dependency>
<dependency>
<artifactId>standard</artifactId>
<groupId>taglibs</groupId>
<version>1.1.2</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<version>2.5</version>
<scope>provided</scope>
</dependency>
</dependencies>
<build>
<finalName>${project.artifactId}</finalName>
<plugins>
<plugin>
<artifactId>maven-remote-resources-plugin</artifactId>
<version>1.2</version>
<configuration>
<!-- prevents the maven-war-plugin from including the resources in WEB-INF/classes -->
<attached>false</attached>
</configuration>
</plugin>
<plugin>
<artifactId>maven-war-plugin</artifactId>
<version>2.1.1</version>
<configuration>
<!-- see http://jira.codehaus.org/browse/MWAR-248 -->
<packagingExcludes>WEB-INF/web.xml</packagingExcludes>
<webResources>
<resource>
<directory>src/main/platform</directory>
<targetPath>WEB-INF</targetPath>
<filtering>true</filtering>
</resource>
<resource>
<directory>${remoteResourcesDirectory}/META-INF</directory>
<targetPath>META-INF</targetPath>
</resource>
</webResources>
</configuration>
</plugin>
</plugins>
</build>
<profiles>
<profile>
<id>deploy</id>
<build>
<plugins>
<plugin>
<artifactId>maven-remote-resources-plugin</artifactId>
<version>1.2</version>
<configuration>
<!-- prevents the maven-war-plugin from including the resources in WEB-INF/classes -->
<attached>false</attached>
</configuration>
<executions>
<execution>
<id>include-jclouds-properties</id>
<goals>
<goal>process</goal>
</goals>
<configuration>
<resourceBundles>
<resourceBundle>org.jclouds:jclouds-properties:${project.version}</resourceBundle>
</resourceBundles>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<artifactId>maven-war-plugin</artifactId>
<configuration>
<!-- see http://jira.codehaus.org/browse/MWAR-248 -->
<packagingExcludes>WEB-INF/web.xml</packagingExcludes>
<webResources>
<resource>
<directory>src/main/platform</directory>
<targetPath>WEB-INF</targetPath>
<filtering>true</filtering>
</resource>
<resource>
<directory>${remoteResourcesDirectory}/META-INF</directory>
<targetPath>META-INF</targetPath>
</resource>
<resource>
<directory>${remoteResourcesDirectory}</directory>
<targetPath>WEB-INF</targetPath>
<filtering>true</filtering>
<includes>
<include>jclouds.properties</include>
</includes>
</resource>
</webResources>
</configuration>
</plugin>
</plugins>
</build>
</profile>
</profiles>
</project>

View File

@ -17,6 +17,8 @@
==================================================================== ====================================================================
==== ====
A guide to generating Twitter consumer keys and access tokens is at http://tinyurl.com/2fhebgb
Please modify your maven settings.xml like below before attempting to run 'mvn -Plive install' Please modify your maven settings.xml like below before attempting to run 'mvn -Plive install'
<profile> <profile>
@ -25,8 +27,8 @@ Please modify your maven settings.xml like below before attempting to run 'mvn -
<activeByDefault>true</activeByDefault> <activeByDefault>true</activeByDefault>
</activation> </activation>
<properties> <properties>
<bees.appid>yourappid</bees.appid> <bees.apikey>yourapikey</bees.apikey>
<bees.environment>yourenv</bees.environment> <bees.secret>yoursecret</bees.secret>
</properties> </properties>
</profile> </profile>
@ -36,13 +38,15 @@ Please modify your maven settings.xml like below before attempting to run 'mvn -
<activeByDefault>true</activeByDefault> <activeByDefault>true</activeByDefault>
</activation> </activation>
<properties> <properties>
<jclouds.aws-s3.identity>YOUR_ACCESS_KEY_ID</jclouds.aws-s3.identity> <test.aws-s3.identity>YOUR_ACCESS_KEY_ID</test.aws-s3.identity>
<jclouds.aws-s3.credential>YOUR_SECRET_KEY</jclouds.aws-s3.credential> <test.aws-s3.credential>YOUR_SECRET_KEY</test.aws-s3.credential>
<jclouds.cloudfiles-us.identity>YOUR_USER</jclouds.cloudfiles-us.identity> <test.cloudfiles-us.identity>YOUR_USER</test.cloudfiles-us.identity>
<jclouds.cloudfiles-us.credential>YOUR_HEX_KEY</jclouds.cloudfiles-us.credential> <test.cloudfiles-us.credential>YOUR_HEX_KEY</test.cloudfiles-us.credential>
<jclouds.azureblob.identity>YOUR_ACCOUNT</jclouds.azureblob.identity> <test.azureblob.identity>YOUR_ACCOUNT</test.azureblob.identity>
<jclouds.azureblob.credential>YOUR_BASE64_ENCODED_KEY</jclouds.azureblob.credential> <test.azureblob.credential>YOUR_BASE64_ENCODED_KEY</test.azureblob.credential>
<jclouds.twitter.identity>YOUR_TWITTER_USERNAME</jclouds.twitter.identity> <test.twitter.runatcloud-tweetstore.consumer.identity>YOUR_TWITTER_CONSUMER_KEY</test.twitter.runatcloud-tweetstore.consumer.identity>
<jclouds.twitter.credential>YOUR_TWITTER_PASSWORD</jclouds.twitter.credential> <test.twitter.runatcloud-tweetstore.consumer.credential>YOUR_TWITTER_CONSUMER_SECRET</test.twitter.runatcloud-tweetstore.consumer.credential>
<test.twitter.runatcloud-tweetstore.access.identity>YOUR_TWITTER_ACCESSTOKEN</test.twitter.runatcloud-tweetstore.access.identity>
<test.twitter.runatcloud-tweetstore.access.credential>YOUR_TWITTER_ACCESSTOKEN_SECRET</test.twitter.runatcloud-tweetstore.access.credential>
</properties> </properties>
</profile> </profile>

View File

@ -22,7 +22,7 @@
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
<parent> <parent>
<groupId>org.jclouds</groupId> <groupId>org.jclouds</groupId>
<artifactId>jclouds-demos-project</artifactId> <artifactId>jclouds-demos-tweetstore-project</artifactId>
<version>1.0-SNAPSHOT</version> <version>1.0-SNAPSHOT</version>
</parent> </parent>
<artifactId>jclouds-demo-runatcloud-tweetstore</artifactId> <artifactId>jclouds-demo-runatcloud-tweetstore</artifactId>
@ -31,91 +31,19 @@
<description>jclouds TweetStore for CloudBees' RUN@cloud using Guice for Dependency Injection</description> <description>jclouds TweetStore for CloudBees' RUN@cloud using Guice for Dependency Injection</description>
<properties> <properties>
<bees.appid>tweetstore</bees.appid> <bees.appid>jclouds/tweetstore</bees.appid>
<bees.environment>run</bees.environment> <bees.environment>run</bees.environment>
<bees.address>localhost</bees.address> <bees.address>localhost</bees.address>
<bees.port>8088</bees.port> <bees.port>8088</bees.port>
<jclouds.tweetstore.blobstores>cloudfiles-us,aws-s3,azureblob</jclouds.tweetstore.blobstores>
<jclouds.tweetstore.container>jclouds-tweetstore-runatcloud</jclouds.tweetstore.container> <jclouds.tweetstore.container>jclouds-tweetstore-runatcloud</jclouds.tweetstore.container>
</properties> </properties>
<dependencies> <dependencies>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>jclouds-blobstore</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.twitter4j</groupId>
<artifactId>twitter4j-core</artifactId>
<version>[2.1,)</version>
</dependency>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>jclouds-blobstore</artifactId>
<version>${project.version}</version>
<type>test-jar</type>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.jclouds.provider</groupId>
<artifactId>aws-s3</artifactId>
<version>${project.version}</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.jclouds.provider</groupId>
<artifactId>cloudfiles-us</artifactId>
<version>${project.version}</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.jclouds.provider</groupId>
<artifactId>azureblob</artifactId>
<version>${project.version}</version>
<scope>runtime</scope>
</dependency>
<dependency> <dependency>
<groupId>com.google.inject.extensions</groupId> <groupId>com.google.inject.extensions</groupId>
<artifactId>guice-servlet</artifactId> <artifactId>guice-servlet</artifactId>
<version>3.0</version> <version>3.0</version>
</dependency> </dependency>
<dependency>
<groupId>displaytag</groupId>
<artifactId>displaytag</artifactId>
<version>1.2</version>
<scope>runtime</scope>
<exclusions>
<exclusion>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-jdk14</artifactId>
<version>1.5.6</version>
<scope>runtime</scope>
</dependency>
<dependency>
<artifactId>jstl</artifactId>
<groupId>javax.servlet</groupId>
<version>1.1.2</version>
<scope>runtime</scope>
</dependency>
<dependency>
<artifactId>standard</artifactId>
<groupId>taglibs</groupId>
<version>1.1.2</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<version>2.5</version>
<scope>provided</scope>
</dependency>
<!-- RUN@cloud API --> <!-- RUN@cloud API -->
<dependency> <dependency>
@ -126,21 +54,7 @@
</dependency> </dependency>
</dependencies> </dependencies>
<pluginRepositories>
<pluginRepository>
<id>bees-plugins-snapshots</id>
<url>http://repository-cloudbees.forge.cloudbees.com/public-snapshot/</url>
<releases>
<enabled>false</enabled>
</releases>
<snapshots>
<enabled>true</enabled>
</snapshots>
</pluginRepository>
</pluginRepositories>
<build> <build>
<finalName>${project.artifactId}</finalName>
<plugins> <plugins>
<plugin> <plugin>
<artifactId>maven-surefire-plugin</artifactId> <artifactId>maven-surefire-plugin</artifactId>
@ -178,11 +92,6 @@
</execution> </execution>
</executions> </executions>
</plugin> </plugin>
<plugin>
<groupId>com.cloudbees</groupId>
<artifactId>bees-maven-plugin</artifactId>
<version>1.0-SNAPSHOT</version>
</plugin>
</plugins> </plugins>
</build> </build>
@ -203,12 +112,20 @@
<configuration> <configuration>
<systemProperties> <systemProperties>
<property> <property>
<name>test.twitter.identity</name> <name>test.twitter.consumer.identity</name>
<value>${test.twitter.identity}</value> <value>${test.twitter.runatcloud-tweetstore.consumer.identity}</value>
</property> </property>
<property> <property>
<name>test.twitter.credential</name> <name>test.twitter.consumer.credential</name>
<value>${test.twitter.credential}</value> <value>${test.twitter.runatcloud-tweetstore.consumer.credential}</value>
</property>
<property>
<name>test.twitter.access.identity</name>
<value>${test.twitter.runatcloud-tweetstore.access.identity}</value>
</property>
<property>
<name>test.twitter.access.credential</name>
<value>${test.twitter.runatcloud-tweetstore.access.credential}</value>
</property> </property>
<property> <property>
<name>test.azureblob.identity</name> <name>test.azureblob.identity</name>
@ -270,5 +187,35 @@
</plugins> </plugins>
</build> </build>
</profile> </profile>
<profile>
<id>deploy</id>
<pluginRepositories>
<pluginRepository>
<id>bees-plugins-snapshots</id>
<url>http://repository-cloudbees.forge.cloudbees.com/public-snapshot</url>
<releases>
<enabled>false</enabled>
</releases>
<snapshots>
<enabled>true</enabled>
</snapshots>
</pluginRepository>
</pluginRepositories>
<build>
<plugins>
<plugin>
<groupId>com.cloudbees</groupId>
<artifactId>bees-maven-plugin</artifactId>
<version>1.0-SNAPSHOT</version>
<configuration>
<environment>${bees.environment}</environment>
<apikey>${bees.apikey}</apikey>
<secret>${bees.secret}</secret>
</configuration>
</plugin>
</plugins>
</build>
</profile>
</profiles> </profiles>
</project> </project>

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