mirror of https://github.com/apache/jclouds.git
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:
commit
e1f0cdcfa5
|
@ -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
|
||||||
|
|
||||||
|
|
|
@ -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>
|
||||||
|
|
|
@ -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")
|
||||||
|
|
|
@ -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))))))
|
|
@ -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
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -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() + "]";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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)) {
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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());
|
||||||
|
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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";
|
||||||
|
|
||||||
|
|
|
@ -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",
|
||||||
|
|
|
@ -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())) {
|
||||||
|
|
|
@ -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();
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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()
|
||||||
|
|
|
@ -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 "adriancolecap-78c" 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
|
||||||
|
|
|
@ -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))))
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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");
|
||||||
|
|
|
@ -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());
|
||||||
|
|
|
@ -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));
|
||||||
}
|
}
|
||||||
|
|
|
@ -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");
|
||||||
|
|
|
@ -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;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -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) {
|
||||||
|
|
|
@ -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
|
||||||
|
|
||||||
|
|
|
@ -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++)
|
||||||
|
|
|
@ -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));
|
||||||
|
|
|
@ -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>
|
|
|
@ -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>
|
||||||
|
|
|
@ -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>
|
|
@ -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>
|
|
@ -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;
|
|
@ -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";
|
||||||
}
|
}
|
|
@ -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";
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -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>
|
|
@ -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>
|
|
@ -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";
|
||||||
}
|
}
|
|
@ -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";
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -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>
|
|
@ -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>
|
|
@ -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
Loading…
Reference in New Issue