refactored common location logic in aws and moved elb to its own module

This commit is contained in:
Adrian Cole 2011-01-03 20:20:42 +01:00
parent c9d1ef6d11
commit ada49c2b3b
84 changed files with 2076 additions and 682 deletions

View File

@ -35,7 +35,7 @@
<properties>
<test.elb.endpoint>https://elasticloadbalancing.us-east-1.amazonaws.com</test.elb.endpoint>
<test.elb.apiversion>2009-11-25</test.elb.apiversion>
<test.elb.apiversion>2010-07-01</test.elb.apiversion>
<test.elb.identity>${test.aws.identity}</test.elb.identity>
<test.elb.credential>${test.aws.credential}</test.elb.credential>
</properties>
@ -60,6 +60,12 @@
<type>test-jar</type>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.jclouds</groupId>
<artifactId>jclouds-jsch</artifactId>
<version>${project.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.jclouds</groupId>
<artifactId>jclouds-loadbalancer</artifactId>

View File

@ -17,7 +17,7 @@
* ====================================================================
*/
package org.jclouds.aws.elb;
package org.jclouds.elb;
import static org.jclouds.aws.ec2.reference.EC2Parameters.ACTION;
import static org.jclouds.aws.ec2.reference.EC2Parameters.VERSION;
@ -29,20 +29,23 @@ import javax.ws.rs.FormParam;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import org.jclouds.aws.elb.binders.BindAvailabilityZonesToIndexedFormParams;
import org.jclouds.aws.elb.binders.BindELBInstanceIdsToIndexedFormParams;
import org.jclouds.aws.elb.domain.LoadBalancer;
import org.jclouds.aws.elb.xml.CreateLoadBalancerResponseHandler;
import org.jclouds.aws.elb.xml.DescribeLoadBalancersResponseHandler;
import org.jclouds.aws.elb.xml.RegisterInstancesWithLoadBalancerResponseHandler;
import org.jclouds.aws.filters.FormSigner;
import org.jclouds.elb.binders.BindAvailabilityZonesToIndexedFormParams;
import org.jclouds.elb.binders.BindInstanceIdsToIndexedFormParams;
import org.jclouds.elb.binders.BindLoadBalancerNamesToIndexedFormParams;
import org.jclouds.elb.domain.LoadBalancer;
import org.jclouds.elb.xml.CreateLoadBalancerResponseHandler;
import org.jclouds.elb.xml.DescribeLoadBalancersResponseHandler;
import org.jclouds.elb.xml.RegisterInstancesWithLoadBalancerResponseHandler;
import org.jclouds.location.functions.RegionToEndpointOrProviderIfNull;
import org.jclouds.rest.annotations.BinderParam;
import org.jclouds.rest.annotations.EndpointParam;
import org.jclouds.rest.annotations.ExceptionParser;
import org.jclouds.rest.annotations.FormParams;
import org.jclouds.rest.annotations.RequestFilters;
import org.jclouds.rest.annotations.VirtualHost;
import org.jclouds.rest.annotations.XMLResponseParser;
import org.jclouds.rest.functions.ReturnEmptySetOnNotFoundOr404;
import com.google.common.util.concurrent.ListenableFuture;
@ -56,7 +59,7 @@ import com.google.common.util.concurrent.ListenableFuture;
@FormParams(keys = VERSION, values = ELBAsyncClient.VERSION)
@VirtualHost
public interface ELBAsyncClient {
public static final String VERSION = "2009-11-25";
public static final String VERSION = "2010-07-01";
/**
* @see ELBClient#createLoadBalancerInRegion
@ -66,12 +69,11 @@ public interface ELBAsyncClient {
@XMLResponseParser(CreateLoadBalancerResponseHandler.class)
@FormParams(keys = ACTION, values = "CreateLoadBalancer")
ListenableFuture<String> createLoadBalancerInRegion(
@EndpointParam(parser = RegionToEndpointOrProviderIfNull.class) @Nullable String region,
@FormParam("LoadBalancerName") String name,
@FormParam("Listeners.member.1.Protocol") String protocol,
@FormParam("Listeners.member.1.LoadBalancerPort") int loadBalancerPort,
@FormParam("Listeners.member.1.InstancePort") int instancePort,
@BinderParam(BindAvailabilityZonesToIndexedFormParams.class) String... availabilityZones);
@EndpointParam(parser = RegionToEndpointOrProviderIfNull.class) @Nullable String region,
@FormParam("LoadBalancerName") String name, @FormParam("Listeners.member.1.Protocol") String protocol,
@FormParam("Listeners.member.1.LoadBalancerPort") int loadBalancerPort,
@FormParam("Listeners.member.1.InstancePort") int instancePort,
@BinderParam(BindAvailabilityZonesToIndexedFormParams.class) String... availabilityZones);
/**
* @see ELBClient#deleteLoadBalancerInRegion
@ -80,8 +82,8 @@ public interface ELBAsyncClient {
@Path("/")
@FormParams(keys = ACTION, values = "DeleteLoadBalancer")
ListenableFuture<Void> deleteLoadBalancerInRegion(
@EndpointParam(parser = RegionToEndpointOrProviderIfNull.class) @Nullable String region,
@FormParam("LoadBalancerName") String name);
@EndpointParam(parser = RegionToEndpointOrProviderIfNull.class) @Nullable String region,
@FormParam("LoadBalancerName") String name);
/**
* @see ELBClient#registerInstancesWithLoadBalancerInRegion
@ -90,10 +92,10 @@ public interface ELBAsyncClient {
@Path("/")
@XMLResponseParser(RegisterInstancesWithLoadBalancerResponseHandler.class)
@FormParams(keys = ACTION, values = "RegisterInstancesWithLoadBalancer")
ListenableFuture<? extends Set<String>> registerInstancesWithLoadBalancerInRegion(
@EndpointParam(parser = RegionToEndpointOrProviderIfNull.class) @Nullable String region,
@FormParam("LoadBalancerName") String name,
@BinderParam(BindELBInstanceIdsToIndexedFormParams.class) String... instanceIds);
ListenableFuture<Set<String>> registerInstancesWithLoadBalancerInRegion(
@EndpointParam(parser = RegionToEndpointOrProviderIfNull.class) @Nullable String region,
@FormParam("LoadBalancerName") String name,
@BinderParam(BindInstanceIdsToIndexedFormParams.class) String... instanceIds);
/**
* @see ELBClient#deregisterInstancesWithLoadBalancerInRegion
@ -102,9 +104,9 @@ public interface ELBAsyncClient {
@Path("/")
@FormParams(keys = ACTION, values = "DeregisterInstancesFromLoadBalancer")
ListenableFuture<Void> deregisterInstancesWithLoadBalancerInRegion(
@EndpointParam(parser = RegionToEndpointOrProviderIfNull.class) @Nullable String region,
@FormParam("LoadBalancerName") String name,
@BinderParam(BindELBInstanceIdsToIndexedFormParams.class) String... instanceIds);
@EndpointParam(parser = RegionToEndpointOrProviderIfNull.class) @Nullable String region,
@FormParam("LoadBalancerName") String name,
@BinderParam(BindInstanceIdsToIndexedFormParams.class) String... instanceIds);
/**
* @see ELBClient#describeLoadBalancersInRegion
@ -113,7 +115,9 @@ public interface ELBAsyncClient {
@Path("/")
@XMLResponseParser(DescribeLoadBalancersResponseHandler.class)
@FormParams(keys = ACTION, values = "DescribeLoadBalancers")
ListenableFuture<? extends Set<LoadBalancer>> describeLoadBalancersInRegion(
@EndpointParam(parser = RegionToEndpointOrProviderIfNull.class) @Nullable String region);
@ExceptionParser(ReturnEmptySetOnNotFoundOr404.class)
ListenableFuture<Set<? extends LoadBalancer>> describeLoadBalancersInRegion(
@EndpointParam(parser = RegionToEndpointOrProviderIfNull.class) @Nullable String region,
@BinderParam(BindLoadBalancerNamesToIndexedFormParams.class) String... loadbalancerNames);
}

View File

@ -17,15 +17,15 @@
* ====================================================================
*/
package org.jclouds.aws.elb;
package org.jclouds.elb;
import java.util.Set;
import java.util.concurrent.TimeUnit;
import javax.annotation.Nullable;
import org.jclouds.aws.elb.domain.LoadBalancer;
import org.jclouds.concurrent.Timeout;
import org.jclouds.elb.domain.LoadBalancer;
/**
* Provides access to EC2 Elastic Load Balancer via their REST API.
@ -97,8 +97,9 @@ public interface ELBClient {
/**
* Returns a set of elastic load balancers
* @param region
* @param loadbalancerNames names associated with the LoadBalancers at creation time.
* @return
*/
Set<LoadBalancer> describeLoadBalancersInRegion(@Nullable String region);
Set<? extends LoadBalancer> describeLoadBalancersInRegion(@Nullable String region, String... loadbalancerNames);
}
}

View File

@ -17,13 +17,13 @@
* ====================================================================
*/
package org.jclouds.aws.elb;
package org.jclouds.elb;
import java.util.List;
import java.util.Properties;
import org.jclouds.aws.elb.config.ELBRestClientModule;
import org.jclouds.aws.elb.loadbalancer.config.ELBLoadBalancerContextModule;
import org.jclouds.elb.config.ELBRestClientModule;
import org.jclouds.elb.loadbalancer.config.ELBLoadBalancerContextModule;
import org.jclouds.http.config.JavaUrlHttpCommandExecutorServiceModule;
import org.jclouds.loadbalancer.LoadBalancerServiceContextBuilder;
import org.jclouds.logging.jdk.config.JDKLoggingModule;

View File

@ -17,13 +17,14 @@
* ====================================================================
*/
package org.jclouds.aws.elb;
package org.jclouds.elb;
import static org.jclouds.Constants.PROPERTY_API_VERSION;
import static org.jclouds.Constants.PROPERTY_ENDPOINT;
import static org.jclouds.aws.reference.AWSConstants.PROPERTY_AUTH_TAG;
import static org.jclouds.aws.reference.AWSConstants.PROPERTY_HEADER_TAG;
import static org.jclouds.aws.reference.AWSConstants.PROPERTY_REGIONS;
import static org.jclouds.aws.reference.AWSConstants.PROPERTY_ZONECLIENT_ENDPOINT;
import static org.jclouds.location.reference.LocationConstants.PROPERTY_REGIONS;
import java.util.Properties;
@ -44,18 +45,18 @@ public class ELBPropertiesBuilder extends PropertiesBuilder {
properties.setProperty(PROPERTY_AUTH_TAG, "AWS");
properties.setProperty(PROPERTY_HEADER_TAG, "amz");
properties.setProperty(PROPERTY_API_VERSION, ELBAsyncClient.VERSION);
properties.setProperty(PROPERTY_REGIONS, Joiner.on(',').join(Region.US_EAST_1,
Region.US_WEST_1, Region.EU_WEST_1, Region.AP_SOUTHEAST_1));
properties.setProperty(PROPERTY_ENDPOINT,
"https://elasticloadbalancing.us-east-1.amazonaws.com");
properties.setProperty(PROPERTY_REGIONS,
Joiner.on(',').join(Region.US_EAST_1, Region.US_WEST_1, Region.EU_WEST_1, Region.AP_SOUTHEAST_1));
properties.setProperty(PROPERTY_ENDPOINT, "https://elasticloadbalancing.us-east-1.amazonaws.com");
properties.setProperty(PROPERTY_ENDPOINT + "." + Region.US_EAST_1,
"https://elasticloadbalancing.us-east-1.amazonaws.com");
"https://elasticloadbalancing.us-east-1.amazonaws.com");
properties.setProperty(PROPERTY_ENDPOINT + "." + Region.US_WEST_1,
"https://elasticloadbalancing.us-west-1.amazonaws.com");
"https://elasticloadbalancing.us-west-1.amazonaws.com");
properties.setProperty(PROPERTY_ENDPOINT + "." + Region.EU_WEST_1,
"https://elasticloadbalancing.eu-west-1.amazonaws.com");
"https://elasticloadbalancing.eu-west-1.amazonaws.com");
properties.setProperty(PROPERTY_ENDPOINT + "." + Region.AP_SOUTHEAST_1,
"https://elasticloadbalancing.ap-southeast-1.amazonaws.com");
"https://elasticloadbalancing.ap-southeast-1.amazonaws.com");
properties.setProperty(PROPERTY_ZONECLIENT_ENDPOINT, "https://ec2.us-east-1.amazonaws.com");
return properties;
}

View File

@ -17,7 +17,7 @@
* ====================================================================
*/
package org.jclouds.aws.elb.binders;
package org.jclouds.elb.binders;
import static org.jclouds.aws.ec2.util.EC2Utils.indexStringArrayToFormValuesWithStringFormat;
@ -38,4 +38,4 @@ public class BindAvailabilityZonesToIndexedFormParams implements Binder {
return indexStringArrayToFormValuesWithStringFormat(request, "AvailabilityZones.member.%s", input);
}
}
}

View File

@ -17,7 +17,7 @@
* ====================================================================
*/
package org.jclouds.aws.elb.binders;
package org.jclouds.elb.binders;
import static org.jclouds.aws.ec2.util.EC2Utils.indexStringArrayToFormValuesWithStringFormat;
@ -32,10 +32,10 @@ import org.jclouds.rest.Binder;
* @author Adrian Cole
*/
@Singleton
public class BindELBInstanceIdsToIndexedFormParams implements Binder {
public class BindInstanceIdsToIndexedFormParams implements Binder {
@Override
public <R extends HttpRequest> R bindToRequest(R request, Object input) {
return indexStringArrayToFormValuesWithStringFormat(request, "Instances.member.%s.InstanceId", input);
}
}
}

View File

@ -0,0 +1,22 @@
package org.jclouds.elb.binders;
import static org.jclouds.aws.ec2.util.EC2Utils.indexStringArrayToFormValuesWithStringFormat;
import javax.inject.Singleton;
import org.jclouds.http.HttpRequest;
import org.jclouds.rest.Binder;
/**
* Binds the String [] to form parameters named with LoadBalancerNames.member.index
*
* @author Adrian Cole
*/
@Singleton
public class BindLoadBalancerNamesToIndexedFormParams implements Binder {
@Override
public <R extends HttpRequest> R bindToRequest(R request, Object input) {
return indexStringArrayToFormValuesWithStringFormat(request, "LoadBalancerNames.member.%s", input);
}
}

View File

@ -17,11 +17,11 @@
* ====================================================================
*/
package org.jclouds.aws.elb.config;
package org.jclouds.elb.config;
import org.jclouds.aws.config.AWSFormSigningRestClientModule;
import org.jclouds.aws.elb.ELBAsyncClient;
import org.jclouds.aws.elb.ELBClient;
import org.jclouds.aws.config.WithZonesFormSigningRestClientModule;
import org.jclouds.elb.ELBAsyncClient;
import org.jclouds.elb.ELBClient;
import org.jclouds.http.RequiresHttp;
import org.jclouds.rest.ConfiguresRestClient;
@ -32,9 +32,9 @@ import org.jclouds.rest.ConfiguresRestClient;
*/
@RequiresHttp
@ConfiguresRestClient
public class ELBRestClientModule extends AWSFormSigningRestClientModule<ELBClient, ELBAsyncClient> {
public class ELBRestClientModule extends WithZonesFormSigningRestClientModule<ELBClient, ELBAsyncClient> {
public ELBRestClientModule() {
super(ELBClient.class, ELBAsyncClient.class);
}
}
}

View File

@ -17,7 +17,7 @@
* ====================================================================
*/
package org.jclouds.aws.elb.domain;
package org.jclouds.elb.domain;
import java.util.HashSet;
import java.util.Set;
@ -45,9 +45,8 @@ public class LoadBalancer implements Comparable<LoadBalancer> {
this.loadBalancerListeners = new HashSet<LoadBalancerListener>();
}
public LoadBalancer(String region, String name, Set<String> instanceIds,
Set<String> availabilityZones, String dnsName) {
super();
public LoadBalancer(String region, String name, Set<String> instanceIds, Set<String> availabilityZones,
String dnsName) {
this.region = region;
this.name = name;
this.instanceIds = instanceIds;
@ -125,19 +124,24 @@ public class LoadBalancer implements Comparable<LoadBalancer> {
return name.compareTo(that.name);
}
@Override
public String toString() {
return "[region=" + region + ", name=" + name + ", instanceIds=" + instanceIds + ", availabilityZones="
+ availabilityZones + ", dnsName=" + dnsName + ", appCookieStickinessPolicy=" + appCookieStickinessPolicy
+ ", lBCookieStickinessPolicy=" + lBCookieStickinessPolicy + ", loadBalancerListeners="
+ loadBalancerListeners + "]";
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result
+ ((appCookieStickinessPolicy == null) ? 0 : appCookieStickinessPolicy.hashCode());
result = prime * result + ((appCookieStickinessPolicy == null) ? 0 : appCookieStickinessPolicy.hashCode());
result = prime * result + ((availabilityZones == null) ? 0 : availabilityZones.hashCode());
result = prime * result + ((dnsName == null) ? 0 : dnsName.hashCode());
result = prime * result + ((instanceIds == null) ? 0 : instanceIds.hashCode());
result = prime * result
+ ((lBCookieStickinessPolicy == null) ? 0 : lBCookieStickinessPolicy.hashCode());
result = prime * result
+ ((loadBalancerListeners == null) ? 0 : loadBalancerListeners.hashCode());
result = prime * result + ((lBCookieStickinessPolicy == null) ? 0 : lBCookieStickinessPolicy.hashCode());
result = prime * result + ((loadBalancerListeners == null) ? 0 : loadBalancerListeners.hashCode());
result = prime * result + ((name == null) ? 0 : name.hashCode());
result = prime * result + ((region == null) ? 0 : region.hashCode());
return result;
@ -234,6 +238,11 @@ public class LoadBalancer implements Comparable<LoadBalancer> {
return result;
}
@Override
public String toString() {
return "[policyName=" + policyName + ", cookieName=" + cookieName + "]";
}
@Override
public boolean equals(Object obj) {
if (this == obj)
@ -292,8 +301,7 @@ public class LoadBalancer implements Comparable<LoadBalancer> {
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result
+ ((cookieExpirationPeriod == null) ? 0 : cookieExpirationPeriod.hashCode());
result = prime * result + ((cookieExpirationPeriod == null) ? 0 : cookieExpirationPeriod.hashCode());
result = prime * result + ((policyName == null) ? 0 : policyName.hashCode());
return result;
}
@ -320,6 +328,11 @@ public class LoadBalancer implements Comparable<LoadBalancer> {
return true;
}
@Override
public String toString() {
return "[policyName=" + policyName + ", cookieExpirationPeriod=" + cookieExpirationPeriod + "]";
}
}
public static class LoadBalancerListener {
@ -328,8 +341,8 @@ public class LoadBalancer implements Comparable<LoadBalancer> {
private Integer loadBalancerPort;
private String protocol;
public LoadBalancerListener(Set<String> policyNames, Integer instancePort,
Integer loadBalancerPort, String protocol) {
public LoadBalancerListener(Set<String> policyNames, Integer instancePort, Integer loadBalancerPort,
String protocol) {
super();
this.policyNames = policyNames;
this.instancePort = instancePort;
@ -416,5 +429,11 @@ public class LoadBalancer implements Comparable<LoadBalancer> {
return true;
}
@Override
public String toString() {
return "[policyNames=" + policyNames + ", instancePort=" + instancePort + ", loadBalancerPort="
+ loadBalancerPort + ", protocol=" + protocol + "]";
}
}
}

View File

@ -0,0 +1,56 @@
/**
*
* 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.
* ====================================================================
*/
package org.jclouds.elb.loadbalancer.config;
import org.jclouds.elb.loadbalancer.strategy.ELBDestroyLoadBalancerStrategy;
import org.jclouds.elb.loadbalancer.strategy.ELBGetLoadBalancerMetadataStrategy;
import org.jclouds.elb.loadbalancer.strategy.ELBListLoadBalancersStrategy;
import org.jclouds.elb.loadbalancer.strategy.ELBLoadBalanceNodesStrategy;
import org.jclouds.loadbalancer.config.BindLoadBalancerStrategiesByClass;
import org.jclouds.loadbalancer.strategy.DestroyLoadBalancerStrategy;
import org.jclouds.loadbalancer.strategy.GetLoadBalancerMetadataStrategy;
import org.jclouds.loadbalancer.strategy.ListLoadBalancersStrategy;
import org.jclouds.loadbalancer.strategy.LoadBalanceNodesStrategy;
/**
* @author Adrian Cole
*/
public class ELBBindLoadBalancerStrategiesByClass extends BindLoadBalancerStrategiesByClass {
@Override
protected Class<? extends LoadBalanceNodesStrategy> defineLoadBalanceNodesStrategy() {
return ELBLoadBalanceNodesStrategy.class;
}
@Override
protected Class<? extends DestroyLoadBalancerStrategy> defineDestroyLoadBalancerStrategy() {
return ELBDestroyLoadBalancerStrategy.class;
}
@Override
protected Class<? extends GetLoadBalancerMetadataStrategy> defineGetLoadBalancerMetadataStrategy() {
return ELBGetLoadBalancerMetadataStrategy.class;
}
@Override
protected Class<? extends ListLoadBalancersStrategy> defineListLoadBalancersStrategy() {
return ELBListLoadBalancersStrategy.class;
}
}

View File

@ -0,0 +1,45 @@
/**
*
* 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.
* ====================================================================
*/
package org.jclouds.elb.loadbalancer.config;
import java.util.Set;
import org.jclouds.domain.Location;
import org.jclouds.loadbalancer.config.BindLoadBalancerSuppliersByClass;
import org.jclouds.location.suppliers.FirstZoneOrRegionMatchingRegionId;
import org.jclouds.location.suppliers.ZoneToRegionToProvider;
import com.google.common.base.Supplier;
/**
* @author Adrian Cole
*/
public class ELBBindLoadBalancerSuppliersByClass extends BindLoadBalancerSuppliersByClass {
@Override
protected Class<? extends Supplier<Location>> defineDefaultLocationSupplier() {
return FirstZoneOrRegionMatchingRegionId.class;
}
@Override
protected Class<? extends Supplier<Set<? extends Location>>> defineLocationSupplier() {
return ZoneToRegionToProvider.class;
}
}

View File

@ -17,30 +17,23 @@
* ====================================================================
*/
package org.jclouds.aws.elb.loadbalancer.config;
package org.jclouds.elb.loadbalancer.config;
import org.jclouds.aws.elb.loadbalancer.strategy.ELBDestroyLoadBalancerStrategy;
import org.jclouds.aws.elb.loadbalancer.strategy.ELBLoadBalanceNodesStrategy;
import org.jclouds.http.RequiresHttp;
import org.jclouds.loadbalancer.strategy.DestroyLoadBalancerStrategy;
import org.jclouds.loadbalancer.strategy.LoadBalanceNodesStrategy;
import org.jclouds.rest.ConfiguresRestClient;
import com.google.inject.AbstractModule;
import org.jclouds.loadbalancer.config.BaseLoadBalancerServiceContextModule;
/**
* Configures the ELB connection.
*
* @author Adrian Cole
*/
@RequiresHttp
@ConfiguresRestClient
public class ELBLoadBalancerContextModule extends AbstractModule {
public class ELBLoadBalancerContextModule extends BaseLoadBalancerServiceContextModule {
@Override
protected void configure() {
bind(LoadBalanceNodesStrategy.class).to(ELBLoadBalanceNodesStrategy.class);
bind(DestroyLoadBalancerStrategy.class).to(ELBDestroyLoadBalancerStrategy.class);
install(new ELBBindLoadBalancerSuppliersByClass());
install(new ELBBindLoadBalancerStrategiesByClass());
install(new ELBLoadBalancerServiceDependenciesModule());
super.configure();
}
}
}

View File

@ -0,0 +1,23 @@
package org.jclouds.elb.loadbalancer.config;
import org.jclouds.elb.domain.LoadBalancer;
import org.jclouds.elb.loadbalancer.functions.LoadBalancerToLoadBalancerMetadata;
import org.jclouds.loadbalancer.domain.LoadBalancerMetadata;
import com.google.common.base.Function;
import com.google.inject.AbstractModule;
import com.google.inject.TypeLiteral;
/**
*
* @author Adrian Cole
*/
public class ELBLoadBalancerServiceDependenciesModule extends AbstractModule {
@Override
protected void configure() {
bind(new TypeLiteral<Function<LoadBalancer, LoadBalancerMetadata>>() {
}).to(LoadBalancerToLoadBalancerMetadata.class);
}
}

View File

@ -0,0 +1,59 @@
/**
*
* 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.
* ====================================================================
*/
package org.jclouds.elb.loadbalancer.functions;
import java.util.Map;
import javax.inject.Inject;
import javax.inject.Singleton;
import org.jclouds.domain.Location;
import org.jclouds.elb.domain.LoadBalancer;
import org.jclouds.loadbalancer.domain.LoadBalancerMetadata;
import org.jclouds.loadbalancer.domain.LoadBalancerType;
import org.jclouds.loadbalancer.domain.internal.LoadBalancerMetadataImpl;
import com.google.common.base.Function;
import com.google.common.base.Supplier;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
/**
*
* @author Adrian Cole
*/
@Singleton
public class LoadBalancerToLoadBalancerMetadata implements Function<LoadBalancer, LoadBalancerMetadata> {
protected final Supplier<Map<String, ? extends Location>> locationMap;
@Inject
public LoadBalancerToLoadBalancerMetadata(Supplier<Map<String, ? extends Location>> locationMap) {
this.locationMap = locationMap;
}
@Override
public LoadBalancerMetadata apply(LoadBalancer input) {
Location location = locationMap.get().get(input.getRegion());
// TODO Builder
return new LoadBalancerMetadataImpl(LoadBalancerType.LB, input.getName(), input.getName(), input.getRegion()
+ "/" + input.getName(), location, null, ImmutableMap.<String, String> of(), ImmutableSet.of(input
.getDnsName()));
}
}

View File

@ -17,21 +17,21 @@
* ====================================================================
*/
package org.jclouds.aws.elb.loadbalancer.strategy;
package org.jclouds.elb.loadbalancer.strategy;
import static com.google.common.base.Preconditions.checkNotNull;
import java.util.Map;
import static org.jclouds.aws.ec2.util.EC2Utils.parseHandle;
import javax.annotation.Resource;
import javax.inject.Inject;
import javax.inject.Named;
import javax.inject.Singleton;
import org.jclouds.aws.ec2.util.EC2Utils;
import org.jclouds.aws.elb.ELBClient;
import org.jclouds.elb.ELBClient;
import org.jclouds.loadbalancer.domain.LoadBalancerMetadata;
import org.jclouds.loadbalancer.reference.LoadBalancerConstants;
import org.jclouds.loadbalancer.strategy.DestroyLoadBalancerStrategy;
import org.jclouds.loadbalancer.strategy.GetLoadBalancerMetadataStrategy;
import org.jclouds.logging.Logger;
/**
@ -45,19 +45,20 @@ public class ELBDestroyLoadBalancerStrategy implements DestroyLoadBalancerStrate
protected Logger logger = Logger.NULL;
private final ELBClient elbClient;
private final GetLoadBalancerMetadataStrategy getLoadBalancer;
@Inject
protected ELBDestroyLoadBalancerStrategy(ELBClient elbClient) {
protected ELBDestroyLoadBalancerStrategy(ELBClient elbClient, GetLoadBalancerMetadataStrategy getLoadBalancer) {
this.elbClient = checkNotNull(elbClient, "elbClient");
this.getLoadBalancer = checkNotNull(getLoadBalancer, "getLoadBalancer");
}
@Override
public boolean execute(String loadBalancer) {
Map<String, String> tuple = EC2Utils.getLoadBalancerNameAndRegionFromDnsName(loadBalancer);
// Only one load balancer per DNS name is expected
for (String key : tuple.keySet()) {
elbClient.deleteLoadBalancerInRegion(key, tuple.get(key));
}
return true;
public LoadBalancerMetadata destroyLoadBalancer(String id) {
String[] parts = parseHandle(id);
String region = parts[0];
String instanceId = parts[1];
elbClient.deleteLoadBalancerInRegion(region, instanceId);
return getLoadBalancer.getLoadBalancer(id);
}
}
}

View File

@ -0,0 +1,47 @@
package org.jclouds.elb.loadbalancer.strategy;
import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.collect.Iterables.getOnlyElement;
import static org.jclouds.aws.ec2.util.EC2Utils.parseHandle;
import java.util.NoSuchElementException;
import javax.inject.Inject;
import javax.inject.Singleton;
import org.jclouds.elb.ELBClient;
import org.jclouds.elb.domain.LoadBalancer;
import org.jclouds.loadbalancer.domain.LoadBalancerMetadata;
import org.jclouds.loadbalancer.strategy.GetLoadBalancerMetadataStrategy;
import com.google.common.base.Function;
/**
*
* @author Adrian Cole
*/
@Singleton
public class ELBGetLoadBalancerMetadataStrategy implements GetLoadBalancerMetadataStrategy {
private final ELBClient client;
private final Function<LoadBalancer, LoadBalancerMetadata> converter;
@Inject
protected ELBGetLoadBalancerMetadataStrategy(ELBClient client, Function<LoadBalancer, LoadBalancerMetadata> converter) {
this.client = checkNotNull(client, "client");
this.converter = checkNotNull(converter, "converter");
}
@Override
public LoadBalancerMetadata getLoadBalancer(String id) {
String[] parts = parseHandle(id);
String region = parts[0];
String instanceId = parts[1];
try {
return converter.apply(getOnlyElement(client.describeLoadBalancersInRegion(region, region, instanceId)));
} catch (NoSuchElementException e) {
return null;
}
}
}

View File

@ -0,0 +1,93 @@
/**
*
* 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.
* ====================================================================
*/
package org.jclouds.elb.loadbalancer.strategy;
import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.collect.Iterables.concat;
import static com.google.common.collect.Iterables.transform;
import static org.jclouds.concurrent.FutureIterables.transformParallel;
import java.util.Set;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Future;
import javax.annotation.Nullable;
import javax.annotation.Resource;
import javax.inject.Inject;
import javax.inject.Named;
import javax.inject.Singleton;
import org.jclouds.Constants;
import org.jclouds.elb.ELBAsyncClient;
import org.jclouds.elb.ELBClient;
import org.jclouds.elb.domain.LoadBalancer;
import org.jclouds.loadbalancer.domain.LoadBalancerMetadata;
import org.jclouds.loadbalancer.reference.LoadBalancerConstants;
import org.jclouds.loadbalancer.strategy.ListLoadBalancersStrategy;
import org.jclouds.location.Region;
import org.jclouds.logging.Logger;
import com.google.common.base.Function;
import com.google.common.util.concurrent.ListenableFuture;
/**
*
* @author Adrian Cole
*/
@Singleton
public class ELBListLoadBalancersStrategy implements ListLoadBalancersStrategy {
@Resource
@Named(LoadBalancerConstants.LOADBALANCER_LOGGER)
protected Logger logger = Logger.NULL;
private final ELBClient client;
private final ELBAsyncClient aclient;
private final Function<LoadBalancer, LoadBalancerMetadata> converter;
private final ExecutorService executor;
private final Set<String> regions;
@Inject
protected ELBListLoadBalancersStrategy(ELBClient client, ELBAsyncClient aclient,
Function<LoadBalancer, LoadBalancerMetadata> converter,
@Named(Constants.PROPERTY_USER_THREADS) ExecutorService executor, @Nullable @Region Set<String> regions) {
this.client = checkNotNull(client, "client");
this.aclient = checkNotNull(aclient, "aclient");
this.regions = checkNotNull(regions, "regions");
this.converter = checkNotNull(converter, "converter");
this.executor = checkNotNull(executor, "executor");
}
@Override
public Iterable<? extends LoadBalancerMetadata> listLoadBalancers() {
Iterable<? extends LoadBalancer> loadBalancers;
if (regions != null)
loadBalancers = concat(transformParallel(regions, new Function<String, Future<Set<? extends LoadBalancer>>>() {
@Override
public ListenableFuture<Set<? extends LoadBalancer>> apply(String from) {
return aclient.describeLoadBalancersInRegion(from);
}
}, executor, null, logger, "loadbalancers"));
else
loadBalancers = client.describeLoadBalancersInRegion(null);
return transform(loadBalancers, converter);
}
}

View File

@ -17,7 +17,10 @@
* ====================================================================
*/
package org.jclouds.aws.elb.loadbalancer.strategy;
package org.jclouds.elb.loadbalancer.strategy;
import static com.google.common.base.Preconditions.checkNotNull;
import static org.jclouds.aws.ec2.compute.util.EC2ComputeUtils.getRegionFromLocationOrNull;
import java.util.ArrayList;
import java.util.List;
@ -28,21 +31,16 @@ import javax.inject.Inject;
import javax.inject.Named;
import javax.inject.Singleton;
import org.jclouds.aws.ec2.util.EC2Utils;
import org.jclouds.aws.ec2.util.EC2Utils.GetRegionFromLocation;
import org.jclouds.aws.elb.ELBClient;
import org.jclouds.compute.domain.NodeMetadata;
import org.jclouds.domain.Location;
import org.jclouds.elb.ELBClient;
import org.jclouds.elb.domain.LoadBalancer;
import org.jclouds.loadbalancer.domain.LoadBalancerMetadata;
import org.jclouds.loadbalancer.domain.LoadBalancerType;
import org.jclouds.loadbalancer.domain.internal.LoadBalancerMetadataImpl;
import org.jclouds.loadbalancer.reference.LoadBalancerConstants;
import org.jclouds.loadbalancer.strategy.LoadBalanceNodesStrategy;
import org.jclouds.logging.Logger;
import com.google.common.base.Function;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Iterables;
import com.google.common.collect.Lists;
@ -55,23 +53,32 @@ public class ELBLoadBalanceNodesStrategy implements LoadBalanceNodesStrategy {
@Resource
@Named(LoadBalancerConstants.LOADBALANCER_LOGGER)
protected Logger logger = Logger.NULL;
protected final ELBClient elbClient;
protected final GetRegionFromLocation getRegionFromLocation;
protected final ELBClient client;
protected final Function<LoadBalancer, LoadBalancerMetadata> converter;
@Inject
protected ELBLoadBalanceNodesStrategy(ELBClient elbClient, GetRegionFromLocation getRegionFromLocation) {
this.elbClient = elbClient;
this.getRegionFromLocation = getRegionFromLocation;
protected ELBLoadBalanceNodesStrategy(ELBClient client, Function<LoadBalancer, LoadBalancerMetadata> converter) {
this.client = checkNotNull(client, "client");
this.converter = checkNotNull(converter, "converter");
}
@Override
public LoadBalancerMetadata execute(Location location, String name, String protocol, int loadBalancerPort,
int instancePort, Iterable<? extends NodeMetadata> nodes) {
String region = getRegionFromLocation.apply(location);
String dnsName = new String();
public LoadBalancerMetadata createLoadBalancerInLocation(Location location, String name, String protocol,
int loadBalancerPort, int instancePort, Iterable<? extends NodeMetadata> nodes) {
checkNotNull(location, "location");
String region = getRegionFromLocationOrNull(location);
dnsName = elbClient.createLoadBalancerInRegion(region, name, protocol, loadBalancerPort, instancePort,
EC2Utils.getAvailabilityZonesForRegion(region));
List<String> availabilityZones = Lists.newArrayList(Iterables.transform(nodes,
new Function<NodeMetadata, String>() {
@Override
public String apply(NodeMetadata from) {
return from.getLocation().getId();
}
}));
client.createLoadBalancerInRegion(region, name, protocol, loadBalancerPort, instancePort,
availabilityZones.toArray(new String[] {}));
List<String> instanceIds = Lists.newArrayList(Iterables.transform(nodes, new Function<NodeMetadata, String>() {
@ -83,7 +90,7 @@ public class ELBLoadBalanceNodesStrategy implements LoadBalanceNodesStrategy {
String[] instanceIdArray = instanceIds.toArray(new String[] {});
Set<String> registeredInstanceIds = elbClient.registerInstancesWithLoadBalancerInRegion(region, name,
Set<String> registeredInstanceIds = client.registerInstancesWithLoadBalancerInRegion(region, name,
instanceIdArray);
// deregister instances
@ -95,10 +102,8 @@ public class ELBLoadBalanceNodesStrategy implements LoadBalanceNodesStrategy {
instanceIdArray[i] = list.get(i);
}
if (instanceIdArray.length > 0)
elbClient.deregisterInstancesWithLoadBalancerInRegion(region, name, instanceIdArray);
client.deregisterInstancesWithLoadBalancerInRegion(region, name, instanceIdArray);
}
return new LoadBalancerMetadataImpl(LoadBalancerType.LB, dnsName, name, dnsName, location, null,
ImmutableMap.<String, String> of(), ImmutableSet.of(dnsName));
return converter.apply(Iterables.getOnlyElement(client.describeLoadBalancersInRegion(region, name)));
}
}
}

View File

@ -17,7 +17,7 @@
* ====================================================================
*/
package org.jclouds.aws.elb.xml;
package org.jclouds.elb.xml;
import javax.annotation.Resource;
@ -52,4 +52,4 @@ public class CreateLoadBalancerResponseHandler extends HandlerWithResult<String>
public String getResult() {
return dnsName;
}
}
}

View File

@ -17,7 +17,7 @@
* ====================================================================
*/
package org.jclouds.aws.elb.xml;
package org.jclouds.elb.xml;
import java.util.Set;
@ -25,14 +25,13 @@ import javax.annotation.Resource;
import javax.inject.Inject;
import org.jclouds.aws.ec2.util.EC2Utils;
import org.jclouds.aws.elb.domain.LoadBalancer;
import org.jclouds.aws.elb.domain.LoadBalancer.AppCookieStickinessPolicy;
import org.jclouds.aws.elb.domain.LoadBalancer.LBCookieStickinessPolicy;
import org.jclouds.aws.elb.domain.LoadBalancer.LoadBalancerListener;
import org.jclouds.date.DateService;
import org.jclouds.elb.domain.LoadBalancer;
import org.jclouds.elb.domain.LoadBalancer.AppCookieStickinessPolicy;
import org.jclouds.elb.domain.LoadBalancer.LBCookieStickinessPolicy;
import org.jclouds.elb.domain.LoadBalancer.LoadBalancerListener;
import org.jclouds.http.HttpRequest;
import org.jclouds.http.functions.ParseSax;
import org.jclouds.location.Region;
import org.jclouds.logging.Logger;
import org.xml.sax.Attributes;
@ -43,23 +42,21 @@ import com.google.common.collect.Sets;
* @author Lili Nadar
*/
public class DescribeLoadBalancersResponseHandler extends
ParseSax.HandlerForGeneratedRequestWithResult<Set<LoadBalancer>> {
@Inject
public DescribeLoadBalancersResponseHandler(@Region String defaultRegion) {
this.defaultRegion = defaultRegion;
this.listenerHandler = new LoadBalancerListenerHandler();
}
ParseSax.HandlerForGeneratedRequestWithResult<Set<LoadBalancer>> {
private final DateService dateService;
private final LoadBalancerListenerHandler listenerHandler;
@Inject
protected DateService dateService;
public DescribeLoadBalancersResponseHandler(DateService dateService, LoadBalancerListenerHandler listenerHandler) {
this.dateService = dateService;
this.listenerHandler = listenerHandler;
}
@Resource
protected Logger logger = Logger.NULL;
private Set<LoadBalancer> contents = Sets.newLinkedHashSet();
private StringBuilder currentText = new StringBuilder();
private final String defaultRegion;
private final LoadBalancerListenerHandler listenerHandler;
private boolean inListenerDescriptions = false;
private boolean inInstances = false;
@ -92,8 +89,7 @@ public class DescribeLoadBalancersResponseHandler extends
}
if (qName.equals("member")) {
if (!(inListenerDescriptions || inAppCookieStickinessPolicies || inInstances
|| inLBCookieStickinessPolicies || inAvailabilityZones)) {
if (!(inListenerDescriptions || inAppCookieStickinessPolicies || inInstances || inLBCookieStickinessPolicies || inAvailabilityZones)) {
elb = new LoadBalancer();
}
}
@ -128,12 +124,9 @@ public class DescribeLoadBalancersResponseHandler extends
if (inAvailabilityZones) {
elb.getAvailabilityZones().add(currentText.toString().trim());
} else if (!(inListenerDescriptions || inAppCookieStickinessPolicies || inInstances
|| inLBCookieStickinessPolicies || inAvailabilityZones)) {
|| inLBCookieStickinessPolicies || inAvailabilityZones)) {
try {
String region = EC2Utils.findRegionInArgsOrNull(getRequest());
if (region == null)
region = defaultRegion;
elb.setRegion(region);
contents.add(elb);
} catch (NullPointerException e) {
@ -165,8 +158,7 @@ public class DescribeLoadBalancersResponseHandler extends
return this;
}
public class LoadBalancerListenerHandler extends
ParseSax.HandlerWithResult<Set<LoadBalancerListener>> {
public static class LoadBalancerListenerHandler extends ParseSax.HandlerWithResult<Set<LoadBalancerListener>> {
private Set<LoadBalancerListener> listeners = Sets.newHashSet();
private StringBuilder currentText = new StringBuilder();
private LoadBalancerListener listener;

View File

@ -17,7 +17,7 @@
* ====================================================================
*/
package org.jclouds.aws.elb.xml;
package org.jclouds.elb.xml;
import java.util.Set;

View File

@ -0,0 +1,192 @@
/**
*
* 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.
* ====================================================================
*/
package org.jclouds.elb;
import static org.testng.Assert.assertEquals;
import java.io.IOException;
import java.lang.reflect.Method;
import java.util.Properties;
import javax.inject.Named;
import org.jclouds.Constants;
import org.jclouds.aws.filters.FormSigner;
import org.jclouds.date.DateService;
import org.jclouds.elb.config.ELBRestClientModule;
import org.jclouds.elb.xml.CreateLoadBalancerResponseHandler;
import org.jclouds.elb.xml.DescribeLoadBalancersResponseHandler;
import org.jclouds.elb.xml.RegisterInstancesWithLoadBalancerResponseHandler;
import org.jclouds.http.HttpRequest;
import org.jclouds.http.RequiresHttp;
import org.jclouds.http.functions.ParseSax;
import org.jclouds.http.functions.ReleasePayloadAndReturn;
import org.jclouds.rest.ConfiguresRestClient;
import org.jclouds.rest.RestClientTest;
import org.jclouds.rest.RestContextFactory;
import org.jclouds.rest.RestContextSpec;
import org.jclouds.rest.functions.MapHttp4xxCodesToExceptions;
import org.jclouds.rest.functions.ReturnEmptySetOnNotFoundOr404;
import org.jclouds.rest.internal.RestAnnotationProcessor;
import org.testng.annotations.Test;
import com.google.inject.Module;
import com.google.inject.TypeLiteral;
/**
* Tests behavior of {@code ELBAsyncClient}
*
* @author Adrian Cole
*/
// NOTE:without testName, this will not call @Before* and fail w/NPE during surefire
@Test(groups = "unit", testName = "ELBAsyncClientTest")
public class ELBAsyncClientTest extends RestClientTest<ELBAsyncClient> {
public void testCreateLoadBalancerInRegion() throws SecurityException, NoSuchMethodException, IOException {
Method method = ELBAsyncClient.class.getMethod("createLoadBalancerInRegion", String.class, String.class,
String.class, int.class, int.class, String[].class);
HttpRequest request = processor.createRequest(method, null, "name", "http", 80, 80);
assertRequestLineEquals(request, "POST https://elasticloadbalancing.us-east-1.amazonaws.com/ HTTP/1.1");
assertNonPayloadHeadersEqual(request, "Host: elasticloadbalancing.us-east-1.amazonaws.com\n");
assertPayloadEquals(
request,
"Version=2010-07-01&Action=CreateLoadBalancer&Listeners.member.1.Protocol=http&LoadBalancerName=name&Listeners.member.1.InstancePort=80&Listeners.member.1.LoadBalancerPort=80",
"application/x-www-form-urlencoded", false);
assertResponseParserClassEquals(method, request, ParseSax.class);
assertSaxResponseParserClassEquals(method, CreateLoadBalancerResponseHandler.class);
assertExceptionParserClassEquals(method, MapHttp4xxCodesToExceptions.class);
checkFilters(request);
}
public void testDescribeLoadBalancers() throws SecurityException, NoSuchMethodException, IOException {
Method method = ELBAsyncClient.class.getMethod("describeLoadBalancersInRegion", String.class, String[].class);
HttpRequest request = processor.createRequest(method, (String) null);
assertRequestLineEquals(request, "POST https://elasticloadbalancing.us-east-1.amazonaws.com/ HTTP/1.1");
assertNonPayloadHeadersEqual(request, "Host: elasticloadbalancing.us-east-1.amazonaws.com\n");
assertPayloadEquals(request, "Version=2010-07-01&Action=DescribeLoadBalancers",
"application/x-www-form-urlencoded", false);
assertResponseParserClassEquals(method, request, ParseSax.class);
assertSaxResponseParserClassEquals(method, DescribeLoadBalancersResponseHandler.class);
assertExceptionParserClassEquals(method, ReturnEmptySetOnNotFoundOr404.class);
checkFilters(request);
}
public void testDescribeLoadBalancersArgs() throws SecurityException, NoSuchMethodException, IOException {
Method method = ELBAsyncClient.class.getMethod("describeLoadBalancersInRegion", String.class, String[].class);
HttpRequest request = processor.createRequest(method, null, "1", "2");
assertRequestLineEquals(request, "POST https://elasticloadbalancing.us-east-1.amazonaws.com/ HTTP/1.1");
assertNonPayloadHeadersEqual(request, "Host: elasticloadbalancing.us-east-1.amazonaws.com\n");
assertPayloadEquals(
request,
"Version=2010-07-01&Action=DescribeLoadBalancers&LoadBalancerNames.member.1=1&LoadBalancerNames.member.2=2",
"application/x-www-form-urlencoded", false);
assertResponseParserClassEquals(method, request, ParseSax.class);
assertSaxResponseParserClassEquals(method, DescribeLoadBalancersResponseHandler.class);
assertExceptionParserClassEquals(method, ReturnEmptySetOnNotFoundOr404.class);
checkFilters(request);
}
public void testRegisterInstancesWithLoadBalancer() throws SecurityException, NoSuchMethodException, IOException {
Method method = ELBAsyncClient.class.getMethod("registerInstancesWithLoadBalancerInRegion", String.class,
String.class, String[].class);
HttpRequest request = processor.createRequest(method, null, "ReferenceAP1", "i-6055fa09");
assertRequestLineEquals(request, "POST https://elasticloadbalancing.us-east-1.amazonaws.com/ HTTP/1.1");
assertNonPayloadHeadersEqual(request, "Host: elasticloadbalancing.us-east-1.amazonaws.com\n");
assertPayloadEquals(
request,
"Version=2010-07-01&Action=RegisterInstancesWithLoadBalancer&LoadBalancerName=ReferenceAP1&Instances.member.1.InstanceId=i-6055fa09",
"application/x-www-form-urlencoded", false);
assertResponseParserClassEquals(method, request, ParseSax.class);
assertSaxResponseParserClassEquals(method, RegisterInstancesWithLoadBalancerResponseHandler.class);
assertExceptionParserClassEquals(method, null);
checkFilters(request);
}
public void testDeregisterInstancesWithLoadBalancer() throws SecurityException, NoSuchMethodException, IOException {
Method method = ELBAsyncClient.class.getMethod("deregisterInstancesWithLoadBalancerInRegion", String.class,
String.class, String[].class);
HttpRequest request = processor.createRequest(method, null, "ReferenceAP1", "i-6055fa09");
assertRequestLineEquals(request, "POST https://elasticloadbalancing.us-east-1.amazonaws.com/ HTTP/1.1");
assertNonPayloadHeadersEqual(request, "Host: elasticloadbalancing.us-east-1.amazonaws.com\n");
assertPayloadEquals(
request,
"Version=2010-07-01&Action=DeregisterInstancesFromLoadBalancer&LoadBalancerName=ReferenceAP1&Instances.member.1.InstanceId=i-6055fa09",
"application/x-www-form-urlencoded", false);
assertResponseParserClassEquals(method, request, ReleasePayloadAndReturn.class);
assertSaxResponseParserClassEquals(method, null);
assertExceptionParserClassEquals(method, null);
checkFilters(request);
}
@Override
protected TypeLiteral<RestAnnotationProcessor<ELBAsyncClient>> createTypeLiteral() {
return new TypeLiteral<RestAnnotationProcessor<ELBAsyncClient>>() {
};
}
@RequiresHttp
@ConfiguresRestClient
private static final class TestELBRestClientModule extends ELBRestClientModule {
@Override
protected void configure() {
super.configure();
}
@Override
protected String provideTimeStamp(final DateService dateService,
@Named(Constants.PROPERTY_SESSION_INTERVAL) int expiration) {
return "2009-11-08T15:54:08.897Z";
}
}
@Override
protected Module createModule() {
return new TestELBRestClientModule();
}
@Override
public RestContextSpec<?, ?> createContextSpec() {
return new RestContextFactory().createContextSpec("elb", "identity", "credential", new Properties());
}
@Override
protected void checkFilters(HttpRequest request) {
assertEquals(request.getFilters().size(), 1);
assertEquals(request.getFilters().get(0).getClass(), FormSigner.class);
}
}

View File

@ -17,22 +17,22 @@
* ====================================================================
*/
package org.jclouds.aws.elb;
package org.jclouds.elb;
import static com.google.common.base.Preconditions.checkNotNull;
import static org.testng.Assert.assertNotNull;
import java.util.Map.Entry;
import java.util.Properties;
import java.util.Set;
import java.util.Map.Entry;
import org.jclouds.Constants;
import org.jclouds.aws.domain.Region;
import org.jclouds.aws.ec2.domain.AvailabilityZone;
import org.jclouds.aws.elb.domain.LoadBalancer;
import org.jclouds.elb.domain.LoadBalancer;
import org.jclouds.loadbalancer.LoadBalancerServiceContextFactory;
import org.jclouds.logging.log4j.config.Log4JLoggingModule;
import org.jclouds.rest.RestContext;
import org.jclouds.rest.RestContextFactory;
import org.testng.annotations.AfterTest;
import org.testng.annotations.BeforeGroups;
import org.testng.annotations.Test;
@ -61,10 +61,9 @@ public class ELBClientLiveTest {
protected void setupCredentials() {
identity = checkNotNull(System.getProperty("test." + provider + ".identity"), "test." + provider + ".identity");
credential = checkNotNull(System.getProperty("test." + provider + ".credential"), "test." + provider
+ ".credential");
endpoint = checkNotNull(System.getProperty("test." + provider + ".endpoint"), "test." + provider + ".endpoint");
apiversion = checkNotNull(System.getProperty("test." + provider + ".apiversion"), "test." + provider
+ ".apiversion");
+ ".credential");
endpoint = System.getProperty("test." + provider + ".endpoint");
apiversion = System.getProperty("test." + provider + ".apiversion");
}
protected Properties setupProperties() {
@ -72,9 +71,12 @@ public class ELBClientLiveTest {
overrides.setProperty(Constants.PROPERTY_TRUST_ALL_CERTS, "true");
overrides.setProperty(Constants.PROPERTY_RELAX_HOSTNAME, "true");
overrides.setProperty(provider + ".identity", identity);
overrides.setProperty(provider + ".credential", credential);
overrides.setProperty(provider + ".endpoint", endpoint);
overrides.setProperty(provider + ".apiversion", apiversion);
if (credential != null)
overrides.setProperty(provider + ".credential", credential);
if (endpoint != null)
overrides.setProperty(provider + ".endpoint", endpoint);
if (apiversion != null)
overrides.setProperty(provider + ".apiversion", apiversion);
return overrides;
}
@ -82,8 +84,8 @@ public class ELBClientLiveTest {
public void setupClient() {
setupCredentials();
Properties overrides = setupProperties();
context = new RestContextFactory().createContext(provider, ImmutableSet.<Module> of(new Log4JLoggingModule()),
overrides);
context = new LoadBalancerServiceContextFactory().createContext(provider,
ImmutableSet.<Module> of(new Log4JLoggingModule()), overrides).getProviderSpecificContext();
client = context.getApi();
}
@ -91,10 +93,10 @@ public class ELBClientLiveTest {
void testCreateLoadBalancer() {
String name = "TestLoadBalancer";
for (Entry<String, String> regionZone : ImmutableMap.<String, String> of(Region.US_EAST_1,
AvailabilityZone.US_EAST_1A, Region.US_WEST_1, AvailabilityZone.US_WEST_1A, Region.EU_WEST_1,
AvailabilityZone.EU_WEST_1A, Region.AP_SOUTHEAST_1, AvailabilityZone.AP_SOUTHEAST_1A).entrySet()) {
String dnsName = client.createLoadBalancerInRegion(regionZone.getKey(), name, "http", 80, 80, regionZone
.getValue());
AvailabilityZone.US_EAST_1A, Region.US_WEST_1, AvailabilityZone.US_WEST_1A, Region.EU_WEST_1,
AvailabilityZone.EU_WEST_1A, Region.AP_SOUTHEAST_1, AvailabilityZone.AP_SOUTHEAST_1A).entrySet()) {
String dnsName = client.createLoadBalancerInRegion(regionZone.getKey(), name, "http", 80, 80,
regionZone.getValue());
assertNotNull(dnsName);
assert (dnsName.startsWith(name));
}
@ -103,8 +105,8 @@ public class ELBClientLiveTest {
@Test(dependsOnMethods = "testCreateLoadBalancer")
void testDescribeLoadBalancers() {
for (String region : Lists.newArrayList(null, Region.EU_WEST_1, Region.US_EAST_1, Region.US_WEST_1,
Region.AP_SOUTHEAST_1)) {
Set<LoadBalancer> allResults = client.describeLoadBalancersInRegion(region);
Region.AP_SOUTHEAST_1)) {
Set<? extends LoadBalancer> allResults = client.describeLoadBalancersInRegion(region);
assertNotNull(allResults);
assert (allResults.size() >= 1);
}
@ -113,7 +115,7 @@ public class ELBClientLiveTest {
@Test
void testDeleteLoadBalancer() {
for (String region : Lists.newArrayList(null, Region.EU_WEST_1, Region.US_EAST_1, Region.US_WEST_1,
Region.AP_SOUTHEAST_1)) {
Region.AP_SOUTHEAST_1)) {
client.deleteLoadBalancerInRegion(region, "TestLoadBalancer");
}
}

View File

@ -0,0 +1,41 @@
/**
*
* 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.
* ====================================================================
*/
package org.jclouds.elb;
import org.jclouds.rest.Providers;
import org.testng.annotations.Test;
import com.google.common.collect.Iterables;
/**
*
* @author Adrian Cole
*
*/
@Test(groups = "unit")
public class ProvidersInPropertiesTest {
@Test
public void testSupportedProviders() {
Iterable<String> providers = Providers.getSupportedProviders();
assert Iterables.contains(providers, "elb") : providers;
}
}

View File

@ -17,7 +17,7 @@
* ====================================================================
*/
package org.jclouds.aws.elb.loadbalancer;
package org.jclouds.elb.loadbalancer;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertNotNull;
@ -26,14 +26,13 @@ import java.util.HashSet;
import java.util.Set;
import org.jclouds.aws.domain.Region;
import org.jclouds.aws.elb.ELBAsyncClient;
import org.jclouds.aws.elb.ELBClient;
import org.jclouds.aws.elb.domain.LoadBalancer;
import org.jclouds.compute.domain.NodeMetadata;
import org.jclouds.elb.ELBAsyncClient;
import org.jclouds.elb.ELBClient;
import org.jclouds.elb.domain.LoadBalancer;
import org.jclouds.loadbalancer.BaseLoadBalancerServiceLiveTest;
import org.jclouds.rest.RestContext;
import org.jclouds.ssh.jsch.config.JschSshClientModule;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.Test;
/**
@ -43,9 +42,7 @@ import org.testng.annotations.Test;
@Test(groups = "live", sequential = true)
public class ELBLoadBalancerServiceLiveTest extends BaseLoadBalancerServiceLiveTest {
@BeforeClass
@Override
public void setServiceDefaults() {
public ELBLoadBalancerServiceLiveTest() {
provider = "elb";
computeProvider = "ec2";
}
@ -66,7 +63,7 @@ public class ELBLoadBalancerServiceLiveTest extends BaseLoadBalancerServiceLiveT
for (NodeMetadata node : nodes) {
instanceIds.add(node.getProviderId());
}
Set<LoadBalancer> elbs = elbClient.describeLoadBalancersInRegion(Region.US_EAST_1);
Set<? extends LoadBalancer> elbs = elbClient.describeLoadBalancersInRegion(Region.US_EAST_1);
assertNotNull(elbs);
for (LoadBalancer elb : elbs) {
if (elb.getName().equals(tag))

View File

@ -17,7 +17,7 @@
* ====================================================================
*/
package org.jclouds.aws.elb.xml;
package org.jclouds.elb.xml;
import static org.easymock.EasyMock.expect;
import static org.easymock.classextension.EasyMock.createMock;
@ -27,8 +27,8 @@ import static org.testng.Assert.assertEquals;
import java.io.InputStream;
import java.util.Set;
import org.jclouds.aws.ec2.xml.BaseEC2HandlerTest;
import org.jclouds.aws.elb.domain.LoadBalancer;
import org.jclouds.elb.domain.LoadBalancer;
import org.jclouds.http.functions.BaseHandlerTest;
import org.jclouds.http.functions.ParseSax;
import org.jclouds.rest.internal.GeneratedHttpRequest;
import org.testng.annotations.Test;
@ -42,17 +42,17 @@ import com.google.common.collect.Sets;
*
* @author Adrian Cole
*/
//NOTE:without testName, this will not call @Before* and fail w/NPE during surefire
// NOTE:without testName, this will not call @Before* and fail w/NPE during surefire
@Test(groups = "unit", testName = "DescribeLoadBalancerResponseHandlerTest")
public class DescribeLoadBalancerResponseHandlerTest extends BaseEC2HandlerTest {
public class DescribeLoadBalancerResponseHandlerTest extends BaseHandlerTest {
public void testParse() {
InputStream is = getClass().getResourceAsStream("/elb/describe_loadbalancers.xml");
InputStream is = getClass().getResourceAsStream("/describe_loadbalancers.xml");
Set<LoadBalancer> contents = Sets.newHashSet();
LoadBalancer dummy = new LoadBalancer(defaultRegion, "my-load-balancer", ImmutableSet.of(
"i-5b33e630", "i-8f26d7e4", "i-5933e632"), ImmutableSet.of("us-east-1a"),
"my-load-balancer-1400212309.us-east-1.elb.amazonaws.com");
LoadBalancer dummy = new LoadBalancer(null, "my-load-balancer", ImmutableSet.of("i-5b33e630",
"i-8f26d7e4", "i-5933e632"), ImmutableSet.of("us-east-1a"),
"my-load-balancer-1400212309.us-east-1.elb.amazonaws.com");
contents.add(dummy);
Set<LoadBalancer> result = parseLoadBalancers(is);
@ -61,8 +61,7 @@ public class DescribeLoadBalancerResponseHandlerTest extends BaseEC2HandlerTest
}
private Set<LoadBalancer> parseLoadBalancers(InputStream is) {
DescribeLoadBalancersResponseHandler handler = injector
.getInstance(DescribeLoadBalancersResponseHandler.class);
DescribeLoadBalancersResponseHandler handler = injector.getInstance(DescribeLoadBalancersResponseHandler.class);
addDefaultRegionToHandler(handler);
Set<LoadBalancer> result = factory.create(handler).parse(is);
return result;
@ -70,7 +69,7 @@ public class DescribeLoadBalancerResponseHandlerTest extends BaseEC2HandlerTest
private void addDefaultRegionToHandler(ParseSax.HandlerWithResult<?> handler) {
GeneratedHttpRequest<?> request = createMock(GeneratedHttpRequest.class);
expect(request.getArgs()).andReturn(ImmutableList.<Object>of());
expect(request.getArgs()).andReturn(ImmutableList.<Object> of());
replay(request);
handler.setContext(request);
}

View File

@ -17,14 +17,14 @@
* ====================================================================
*/
package org.jclouds.aws.elb.xml;
package org.jclouds.elb.xml;
import static org.testng.Assert.assertEquals;
import java.io.InputStream;
import java.util.Set;
import org.jclouds.aws.ec2.xml.BaseEC2HandlerTest;
import org.jclouds.http.functions.BaseHandlerTest;
import org.testng.annotations.Test;
import com.google.common.collect.Sets;
@ -34,13 +34,12 @@ import com.google.common.collect.Sets;
*
* @author Adrian Cole
*/
//NOTE:without testName, this will not call @Before* and fail w/NPE during surefire
// NOTE:without testName, this will not call @Before* and fail w/NPE during surefire
@Test(groups = "unit", testName = "RegisterInstancesWithLoadBalancerResponseHandlerTest")
public class RegisterInstancesWithLoadBalancerResponseHandlerTest extends BaseEC2HandlerTest {
public class RegisterInstancesWithLoadBalancerResponseHandlerTest extends BaseHandlerTest {
public void testParse() {
InputStream is = getClass().getResourceAsStream(
"/ec2/register_instances_with_loadbalancer.xml");
InputStream is = getClass().getResourceAsStream("/register_instances_with_loadbalancer.xml");
Set<String> instanceIds = Sets.newHashSet();
instanceIds.add("i-6055fa09");
@ -53,7 +52,7 @@ public class RegisterInstancesWithLoadBalancerResponseHandlerTest extends BaseEC
private Set<String> parseXML(InputStream is) {
RegisterInstancesWithLoadBalancerResponseHandler handler = injector
.getInstance(RegisterInstancesWithLoadBalancerResponseHandler.class);
.getInstance(RegisterInstancesWithLoadBalancerResponseHandler.class);
Set<String> result = factory.create(handler).parse(is);
return result;
}

View File

@ -0,0 +1,155 @@
<?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.
====================================================================
-->
<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">
<!--
For more configuration infromation and examples see the Apache
Log4j website: http://logging.apache.org/log4j/
-->
<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/"
debug="false">
<!-- A time/date based rolling appender -->
<appender name="WIREFILE" class="org.apache.log4j.DailyRollingFileAppender">
<param name="File" value="target/test-data/jclouds-wire.log" />
<param name="Append" value="true" />
<!-- Rollover at midnight each day -->
<param name="DatePattern" value="'.'yyyy-MM-dd" />
<param name="Threshold" value="TRACE" />
<layout class="org.apache.log4j.PatternLayout">
<!-- The default pattern: Date Priority [Category] Message\n -->
<param name="ConversionPattern" value="%d %-5p [%c] (%t) %m%n" />
<!--
The full pattern: Date MS Priority [Category]
(Thread:NDC) Message\n <param name="ConversionPattern"
value="%d %-5r %-5p [%c] (%t:%x) %m%n"/>
-->
</layout>
</appender>
<!-- A time/date based rolling appender -->
<appender name="FILE" class="org.apache.log4j.DailyRollingFileAppender">
<param name="File" value="target/test-data/jclouds.log" />
<param name="Append" value="true" />
<!-- Rollover at midnight each day -->
<param name="DatePattern" value="'.'yyyy-MM-dd" />
<param name="Threshold" value="TRACE" />
<layout class="org.apache.log4j.PatternLayout">
<!-- The default pattern: Date Priority [Category] Message\n -->
<param name="ConversionPattern" value="%d %-5p [%c] (%t) %m%n" />
<!--
The full pattern: Date MS Priority [Category]
(Thread:NDC) Message\n <param name="ConversionPattern"
value="%d %-5r %-5p [%c] (%t:%x) %m%n"/>
-->
</layout>
</appender>
<!-- A time/date based rolling appender -->
<appender name="LOADBALANCERFILE" class="org.apache.log4j.DailyRollingFileAppender">
<param name="File" value="target/test-data/jclouds-loadbalancer.log" />
<param name="Append" value="true" />
<param name="DatePattern" value="'.'yyyy-MM-dd" />
<param name="Threshold" value="TRACE" />
<layout class="org.apache.log4j.PatternLayout">
<param name="ConversionPattern" value="%d %-5p [%c] (%t) %m%n" />
</layout>
</appender>
<!-- A time/date based rolling appender -->
<appender name="COMPUTEFILE" class="org.apache.log4j.DailyRollingFileAppender">
<param name="File" value="target/test-data/jclouds-compute.log" />
<param name="Append" value="true" />
<!-- Rollover at midnight each day -->
<param name="DatePattern" value="'.'yyyy-MM-dd" />
<param name="Threshold" value="TRACE" />
<layout class="org.apache.log4j.PatternLayout">
<!-- The default pattern: Date Priority [Category] Message\n -->
<param name="ConversionPattern" value="%d %-5p [%c] (%t) %m%n" />
<!--
The full pattern: Date MS Priority [Category]
(Thread:NDC) Message\n <param name="ConversionPattern"
value="%d %-5r %-5p [%c] (%t:%x) %m%n"/>
-->
</layout>
</appender>
<appender name="ASYNCCOMPUTE" class="org.apache.log4j.AsyncAppender">
<appender-ref ref="COMPUTEFILE" />
</appender>
<appender name="ASYNC" class="org.apache.log4j.AsyncAppender">
<appender-ref ref="FILE" />
</appender>
<appender name="ASYNCWIRE" class="org.apache.log4j.AsyncAppender">
<appender-ref ref="WIREFILE" />
</appender>
<appender name="ASYNCLOADBALANCER" class="org.apache.log4j.AsyncAppender">
<appender-ref ref="LOADBALANCERFILE" />
</appender>
<!-- ================ -->
<!-- Limit categories -->
<!-- ================ -->
<category name="org.jclouds">
<priority value="DEBUG" />
<appender-ref ref="ASYNC" />
</category>
<category name="jclouds.headers">
<priority value="DEBUG" />
<appender-ref ref="ASYNCWIRE" />
</category>
<category name="jclouds.wire">
<priority value="DEBUG" />
<appender-ref ref="ASYNCWIRE" />
</category>
<category name="jclouds.loadbalancer">
<priority value="DEBUG" />
<appender-ref ref="ASYNCLOADBALANCER" />
</category>
<category name="jclouds.compute">
<priority value="TRACE" />
<appender-ref ref="ASYNCCOMPUTE" />
</category>
<!-- ======================= -->
<!-- Setup the Root category -->
<!-- ======================= -->
<root>
<priority value="WARN" />
</root>
</log4j:configuration>

View File

@ -19,7 +19,7 @@
package org.jclouds.simpledb.config;
import org.jclouds.aws.config.AWSFormSigningRestClientModule;
import org.jclouds.aws.config.FormSigningRestClientModule;
import org.jclouds.http.RequiresHttp;
import org.jclouds.rest.ConfiguresRestClient;
import org.jclouds.simpledb.SimpleDBAsyncClient;
@ -33,7 +33,7 @@ import org.jclouds.simpledb.SimpleDBClient;
*/
@RequiresHttp
@ConfiguresRestClient
public class SimpleDBRestClientModule extends AWSFormSigningRestClientModule<SimpleDBClient, SimpleDBAsyncClient> {
public class SimpleDBRestClientModule extends FormSigningRestClientModule<SimpleDBClient, SimpleDBAsyncClient> {
public SimpleDBRestClientModule() {
super(SimpleDBClient.class, SimpleDBAsyncClient.class);

View File

@ -23,7 +23,7 @@ import static org.jclouds.Constants.PROPERTY_API_VERSION;
import static org.jclouds.Constants.PROPERTY_ENDPOINT;
import static org.jclouds.aws.reference.AWSConstants.PROPERTY_AUTH_TAG;
import static org.jclouds.aws.reference.AWSConstants.PROPERTY_HEADER_TAG;
import static org.jclouds.aws.reference.AWSConstants.PROPERTY_REGIONS;
import static org.jclouds.location.reference.LocationConstants.PROPERTY_REGIONS;
import java.util.Properties;

View File

@ -21,7 +21,7 @@ package org.jclouds.aws.cloudwatch.config;
import org.jclouds.aws.cloudwatch.CloudWatchAsyncClient;
import org.jclouds.aws.cloudwatch.CloudWatchClient;
import org.jclouds.aws.config.AWSFormSigningRestClientModule;
import org.jclouds.aws.config.FormSigningRestClientModule;
import org.jclouds.http.RequiresHttp;
import org.jclouds.rest.ConfiguresRestClient;
@ -32,7 +32,7 @@ import org.jclouds.rest.ConfiguresRestClient;
*/
@RequiresHttp
@ConfiguresRestClient
public class CloudWatchRestClientModule extends AWSFormSigningRestClientModule<CloudWatchClient, CloudWatchAsyncClient> {
public class CloudWatchRestClientModule extends FormSigningRestClientModule<CloudWatchClient, CloudWatchAsyncClient> {
public CloudWatchRestClientModule() {
super(CloudWatchClient.class, CloudWatchAsyncClient.class);
}

View File

@ -19,21 +19,14 @@
package org.jclouds.aws.config;
import static com.google.common.collect.Iterables.find;
import static com.google.common.collect.Iterables.get;
import static com.google.common.collect.Maps.newLinkedHashMap;
import static org.jclouds.aws.reference.AWSConstants.PROPERTY_REGIONS;
import java.net.URI;
import java.util.Map;
import java.util.Map.Entry;
import java.util.NoSuchElementException;
import java.util.Set;
import javax.annotation.Nullable;
import javax.inject.Singleton;
import org.jclouds.Constants;
import org.jclouds.aws.handlers.AWSClientErrorRetryHandler;
import org.jclouds.aws.handlers.AWSRedirectionRetryHandler;
import org.jclouds.aws.handlers.ParseAWSErrorFromXmlContent;
@ -49,16 +42,12 @@ import org.jclouds.logging.Logger.LoggerFactory;
import org.jclouds.rest.ConfiguresRestClient;
import org.jclouds.rest.config.RestClientModule;
import com.google.common.base.Predicate;
import com.google.common.base.Splitter;
import com.google.inject.ConfigurationException;
import com.google.inject.Injector;
import com.google.inject.Key;
import com.google.common.collect.ImmutableBiMap;
import com.google.inject.Provides;
import com.google.inject.name.Names;
import com.google.inject.Scopes;
import com.google.inject.TypeLiteral;
/**
* Configures the S3 connection, including logging and http transport.
*
* @author Adrian Cole
*/
@ -74,56 +63,6 @@ public class AWSRestClientModule<S, A> extends RestClientModule<S, A> {
super(syncClientType, asyncClientType);
}
@Provides
@Singleton
@Region
@Nullable
protected Map<String, URI> provideRegions(Injector injector) {
try {
String regionString = injector.getInstance(Key.get(String.class, Names.named(PROPERTY_REGIONS)));
Map<String, URI> regions = newLinkedHashMap();
for (String region : Splitter.on(',').split(regionString)) {
regions.put(
region,
URI.create(injector.getInstance(Key.get(String.class,
Names.named(Constants.PROPERTY_ENDPOINT + "." + region)))));
}
return regions;
} catch (ConfigurationException e) {
// this happens if regions property isn't set
// services not run by AWS may not have regions, so this is ok.
return null;
}
}
@Provides
@Singleton
@Region
protected Set<String> provideRegions(@Region Map<String, URI> map) {
return map.keySet();
}
@Provides
@Singleton
@Region
protected String getDefaultRegion(@Provider final URI uri, @Region Map<String, URI> map, LoggerFactory logFactory) {
try {
return find(map.entrySet(), new Predicate<Entry<String, URI>>() {
@Override
public boolean apply(Entry<String, URI> input) {
return input.getValue().equals(uri);
}
}).getKey();
} catch (NoSuchElementException e) {
String region = get(map.keySet(), 0);
logFactory.getLogger("jclouds.compute").warn(
"failed to find region for current endpoint %s in %s; choosing first: %s", uri, map, region);
return region;
}
}
@Override
protected void bindErrorHandlers() {
bind(HttpErrorHandler.class).annotatedWith(Redirection.class).to(ParseAWSErrorFromXmlContent.class);
@ -137,4 +76,39 @@ public class AWSRestClientModule<S, A> extends RestClientModule<S, A> {
bind(HttpRetryHandler.class).annotatedWith(ClientError.class).to(AWSClientErrorRetryHandler.class);
}
@Provides
@Singleton
@Region
protected String getDefaultRegion(@Provider URI uri, @Region Map<String, URI> map, LoggerFactory logFactory) {
String region = ImmutableBiMap.copyOf(map).inverse().get(uri);
if (region == null) {
logFactory.getLogger(getClass().getName()).warn(
"failed to find region for current endpoint %s in %s; choosing first: %s", uri, map, region);
region = get(map.keySet(), 0);
}
return region;
}
protected void bindRegionsToProvider() {
bindRegionsToProvider(ProvideRegionsViaProperties.class);
}
@Override
protected void configure() {
super.configure();
bindRegionsToProvider();
}
protected void bindRegionsToProvider(Class<? extends javax.inject.Provider<Map<String, URI>>> providerClass) {
bind(new TypeLiteral<Map<String, URI>>() {
}).annotatedWith(Region.class).toProvider(providerClass).in(Scopes.SINGLETON);
}
@Provides
@Singleton
@Region
protected Set<String> provideRegions(@Region Map<String, URI> map) {
return map.keySet();
}
}

View File

@ -36,20 +36,19 @@ import org.jclouds.rest.RequestSigner;
import com.google.inject.Provides;
/**
* Configures the S3 connection, including logging and http transport.
*
* @author Adrian Cole
*/
@ConfiguresRestClient
@RequiresHttp
public class AWSFormSigningRestClientModule<S, A> extends AWSRestClientModule<S, A> {
public class FormSigningRestClientModule<S, A> extends AWSRestClientModule<S, A> {
public AWSFormSigningRestClientModule(Class<S> syncClientType, Class<A> asyncClientType,
Map<Class<?>, Class<?>> delegates) {
public FormSigningRestClientModule(Class<S> syncClientType, Class<A> asyncClientType,
Map<Class<?>, Class<?>> delegates) {
super(syncClientType, asyncClientType, delegates);
}
public AWSFormSigningRestClientModule(Class<S> syncClientType, Class<A> asyncClientType) {
public FormSigningRestClientModule(Class<S> syncClientType, Class<A> asyncClientType) {
super(syncClientType, asyncClientType);
}

View File

@ -0,0 +1,55 @@
package org.jclouds.aws.config;
import static org.jclouds.location.reference.LocationConstants.PROPERTY_REGIONS;
import java.net.URI;
import java.util.Map;
import javax.inject.Inject;
import javax.inject.Singleton;
import org.jclouds.Constants;
import org.jclouds.location.Provider;
import org.jclouds.location.Region;
import com.google.common.base.Splitter;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableMap.Builder;
import com.google.inject.ConfigurationException;
import com.google.inject.Injector;
import com.google.inject.Key;
import com.google.inject.name.Names;
@Singleton
public class ProvideRegionsViaProperties implements javax.inject.Provider<Map<String, URI>> {
private final Injector injector;
@Inject
ProvideRegionsViaProperties(Injector injector) {
this.injector = injector;
}
@Singleton
@Region
@Override
public Map<String, URI> get() {
try {
String regionString = injector.getInstance(Key.get(String.class, Names.named(PROPERTY_REGIONS)));
Builder<String, URI> regions = ImmutableMap.<String, URI> builder();
for (String region : Splitter.on(',').split(regionString)) {
regions.put(
region,
URI.create(injector.getInstance(Key.get(String.class,
Names.named(Constants.PROPERTY_ENDPOINT + "." + region)))));
}
return regions.build();
} catch (ConfigurationException e) {
// this happens if regions property isn't set
// services not run by AWS may not have regions, so this is ok.
return ImmutableMap.of(injector.getInstance(Key.get(String.class, Provider.class)),
injector.getInstance(Key.get(URI.class, Provider.class)));
}
}
}

View File

@ -0,0 +1,168 @@
/**
*
* 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.
* ====================================================================
*/
package org.jclouds.aws.config;
import java.net.URI;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.TimeUnit;
import javax.inject.Inject;
import javax.inject.Named;
import javax.inject.Singleton;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import org.jclouds.aws.ec2.domain.AvailabilityZoneInfo;
import org.jclouds.aws.ec2.xml.DescribeAvailabilityZonesResponseHandler;
import org.jclouds.aws.ec2.xml.DescribeRegionsResponseHandler;
import org.jclouds.aws.filters.FormSigner;
import org.jclouds.aws.reference.AWSConstants;
import org.jclouds.concurrent.Timeout;
import org.jclouds.concurrent.internal.SyncProxy;
import org.jclouds.internal.ClassMethodArgs;
import org.jclouds.location.Region;
import org.jclouds.location.Zone;
import org.jclouds.rest.AsyncClientFactory;
import org.jclouds.rest.annotations.EndpointParam;
import org.jclouds.rest.annotations.ExceptionParser;
import org.jclouds.rest.annotations.FormParams;
import org.jclouds.rest.annotations.RequestFilters;
import org.jclouds.rest.annotations.VirtualHost;
import org.jclouds.rest.annotations.XMLResponseParser;
import org.jclouds.rest.functions.ReturnEmptySetOnNotFoundOr404;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableMap.Builder;
import com.google.common.util.concurrent.ListenableFuture;
import com.google.inject.AbstractModule;
import com.google.inject.Provides;
/**
*
* @author Adrian Cole
*/
public class ProvidersViaAPI {
@Singleton
public static class RegionIdsToURI implements javax.inject.Provider<Map<String, URI>> {
private final ZoneAndRegionClient client;
private URI endpoint;
@Inject
public RegionIdsToURI(@Zone URI endpoint, ZoneAndRegionClient client) {
this.client = client;
this.endpoint = endpoint;
}
@Singleton
@Region
@Override
public Map<String, URI> get() {
return client.describeRegions(endpoint);
}
}
@Singleton
public static class RegionIdToZoneId implements javax.inject.Provider<Map<String, String>> {
private final ZoneAndRegionClient client;
private final Set<String> regions;
private final RegionIdsToURI regionIdsToURI;
@Inject
public RegionIdToZoneId(RegionIdsToURI regionIdsToURI, ZoneAndRegionClient client, @Region Set<String> regions) {
this.client = client;
this.regions = regions;
this.regionIdsToURI = regionIdsToURI;
}
@Singleton
@Zone
@Override
public Map<String, String> get() {
Builder<String, String> map = ImmutableMap.<String, String> builder();
for (Entry<String, URI> region : regionIdsToURI.get().entrySet()) {
if (regions.contains(region.getKey()))
for (AvailabilityZoneInfo zoneInfo : client.describeAvailabilityZonesInRegion(region.getValue())) {
map.put(zoneInfo.getZone(), region.getKey());
}
}
return map.build();
}
}
static class ProvidesZoneAndRegionClientModule extends AbstractModule {
@Provides
@Singleton
@Zone
URI provideURI(@Named(AWSConstants.PROPERTY_ZONECLIENT_ENDPOINT) String endpoint) {
return URI.create(endpoint);
}
@Provides
@Singleton
ZoneAndRegionClient provideZoneAndRegionClient(AsyncClientFactory factory) throws IllegalArgumentException,
SecurityException, NoSuchMethodException {
return SyncProxy.proxy(ZoneAndRegionClient.class,
new SyncProxy(ZoneAndRegionClient.class, factory.create(ZoneAndRegionAsyncClient.class),
new ConcurrentHashMap<ClassMethodArgs, Object>(), ImmutableMap.<Class<?>, Class<?>> of()));
}
@Override
protected void configure() {
}
}
@RequestFilters(FormSigner.class)
@FormParams(keys = "Version", values = "2010-06-15")
@VirtualHost
static interface ZoneAndRegionAsyncClient {
@POST
@Path("/")
@FormParams(keys = "Action", values = "DescribeAvailabilityZones")
@XMLResponseParser(DescribeAvailabilityZonesResponseHandler.class)
@ExceptionParser(ReturnEmptySetOnNotFoundOr404.class)
ListenableFuture<? extends Set<AvailabilityZoneInfo>> describeAvailabilityZonesInRegion(@EndpointParam URI region);
@POST
@Path("/")
@FormParams(keys = "Action", values = "DescribeRegions")
@XMLResponseParser(DescribeRegionsResponseHandler.class)
ListenableFuture<? extends Map<String, URI>> describeRegions(@EndpointParam URI endpoint);
}
@Timeout(duration = 60, timeUnit = TimeUnit.SECONDS)
static interface ZoneAndRegionClient {
Set<AvailabilityZoneInfo> describeAvailabilityZonesInRegion(URI region);
Map<String, URI> describeRegions(URI endpoint);
}
}

View File

@ -0,0 +1,88 @@
/**
*
* 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.
* ====================================================================
*/
package org.jclouds.aws.config;
import java.net.URI;
import java.util.Map;
import javax.inject.Singleton;
import org.jclouds.aws.config.ProvidersViaAPI.ProvidesZoneAndRegionClientModule;
import org.jclouds.http.RequiresHttp;
import org.jclouds.location.Region;
import org.jclouds.location.Zone;
import org.jclouds.rest.ConfiguresRestClient;
import com.google.common.base.Function;
import com.google.common.collect.Maps;
import com.google.inject.Provides;
import com.google.inject.Scopes;
import com.google.inject.TypeLiteral;
/**
*
* @author Adrian Cole
*/
@ConfiguresRestClient
@RequiresHttp
public class WithZonesFormSigningRestClientModule<S, A> extends FormSigningRestClientModule<S, A> {
public WithZonesFormSigningRestClientModule(Class<S> syncClientType, Class<A> asyncClientType,
Map<Class<?>, Class<?>> delegates) {
super(syncClientType, asyncClientType, delegates);
}
public WithZonesFormSigningRestClientModule(Class<S> syncClientType, Class<A> asyncClientType) {
super(syncClientType, asyncClientType);
}
protected void bindZonesToProvider() {
install(new ProvidesZoneAndRegionClientModule());
bindZonesToProvider(ProvidersViaAPI.RegionIdToZoneId.class);
}
protected void bindZonesToProvider(Class<? extends javax.inject.Provider<Map<String, String>>> providerClass) {
bind(new TypeLiteral<Map<String, String>>() {
}).annotatedWith(Zone.class).toProvider(providerClass).in(Scopes.SINGLETON);
}
@Override
protected void configure() {
super.configure();
bindZonesToProvider();
}
@Provides
@Singleton
@Zone
protected Map<String, URI> provideZones(@Region final Map<String, URI> regionToEndpoint,
@Zone Map<String, String> availabilityZoneToRegion) {
return Maps.transformValues(availabilityZoneToRegion, new Function<String, URI>() {
@Override
public URI apply(String from) {
return regionToEndpoint.get(from);
}
});
}
}

View File

@ -23,11 +23,12 @@ import java.util.Set;
import org.jclouds.aws.ec2.compute.suppliers.EC2HardwareSupplier;
import org.jclouds.aws.ec2.compute.suppliers.EC2ImageSupplier;
import org.jclouds.aws.ec2.compute.suppliers.EC2LocationSupplier;
import org.jclouds.compute.config.BindComputeSuppliersByClass;
import org.jclouds.compute.domain.Hardware;
import org.jclouds.compute.domain.Image;
import org.jclouds.domain.Location;
import org.jclouds.location.suppliers.FirstZoneOrRegionMatchingRegionId;
import org.jclouds.location.suppliers.ZoneToRegionToProvider;
import com.google.common.base.Supplier;
/**
@ -46,11 +47,11 @@ public class EC2BindComputeSuppliersByClass extends BindComputeSuppliersByClass
@Override
protected Class<? extends Supplier<Location>> defineDefaultLocationSupplier() {
return org.jclouds.location.suppliers.FirstZoneOrRegionMatchingRegionId.class;
return FirstZoneOrRegionMatchingRegionId.class;
}
@Override
protected Class<? extends Supplier<Set<? extends Location>>> defineLocationSupplier() {
return EC2LocationSupplier.class;
return ZoneToRegionToProvider.class;
}
}

View File

@ -1,66 +0,0 @@
/**
*
* Copyright (C) 2009 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.aws.ec2.compute.strategy;
import static com.google.common.base.Preconditions.checkNotNull;
import java.util.HashSet;
import java.util.Set;
import javax.annotation.Resource;
import javax.inject.Inject;
import javax.inject.Named;
import javax.inject.Singleton;
import org.jclouds.aws.elb.ELBClient;
import org.jclouds.aws.elb.domain.LoadBalancer;
import org.jclouds.compute.reference.ComputeServiceConstants;
import org.jclouds.compute.strategy.ListLoadBalancersStrategy;
import org.jclouds.logging.Logger;
/**
*
* @author Adrian Cole
*/
@Singleton
public class EC2ListLoadBalancersStrategy implements ListLoadBalancersStrategy {
@Resource
@Named(ComputeServiceConstants.COMPUTE_LOGGER)
protected Logger logger = Logger.NULL;
private final ELBClient elbClient;
@Inject
protected EC2ListLoadBalancersStrategy(ELBClient elbClient) {
this.elbClient = checkNotNull(elbClient, "elbClient");
}
@Override
public Set<String> execute() {
Set<LoadBalancer> loadBalancers = elbClient.describeLoadBalancersInRegion(null);
Set<String> loadBalancerDnsNames = new HashSet<String>();
for(LoadBalancer loadBalancer: loadBalancers)
{
loadBalancerDnsNames.add(loadBalancer.getDnsName());
}
return loadBalancerDnsNames;
}
}

View File

@ -25,8 +25,6 @@ import static com.google.common.collect.Iterables.transform;
import static com.google.common.collect.Sets.newLinkedHashSet;
import static org.jclouds.concurrent.FutureIterables.transformParallel;
import java.net.URI;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Future;
@ -62,16 +60,16 @@ public class EC2ListNodesStrategy implements ListNodesStrategy {
protected Logger logger = Logger.NULL;
private final EC2AsyncClient client;
private final Map<String, URI> regionMap;
private final Set<String> regions;
private final Function<RunningInstance, NodeMetadata> runningInstanceToNodeMetadata;
private final ExecutorService executor;
@Inject
protected EC2ListNodesStrategy(EC2AsyncClient client, @Region Map<String, URI> regionMap,
protected EC2ListNodesStrategy(EC2AsyncClient client, @Region Set<String> regions,
Function<RunningInstance, NodeMetadata> runningInstanceToNodeMetadata,
@Named(Constants.PROPERTY_USER_THREADS) ExecutorService executor) {
this.client = client;
this.regionMap = regionMap;
this.regions = regions;
this.runningInstanceToNodeMetadata = runningInstanceToNodeMetadata;
this.executor = executor;
}
@ -84,7 +82,7 @@ public class EC2ListNodesStrategy implements ListNodesStrategy {
@Override
public Set<? extends NodeMetadata> listDetailsOnNodesMatching(Predicate<ComputeMetadata> filter) {
Iterable<Set<? extends Reservation<? extends RunningInstance>>> reservations = transformParallel(
regionMap.keySet(), new Function<String, Future<Set<? extends Reservation<? extends RunningInstance>>>>() {
regions, new Function<String, Future<Set<? extends Reservation<? extends RunningInstance>>>>() {
@Override
public Future<Set<? extends Reservation<? extends RunningInstance>>> apply(String from) {

View File

@ -42,16 +42,15 @@ import static com.google.common.collect.Iterables.concat;
import static com.google.common.collect.Iterables.filter;
import static com.google.common.collect.Iterables.transform;
import static com.google.common.collect.Maps.newLinkedHashMap;
import static com.google.common.collect.Maps.transformValues;
import static com.google.common.collect.Maps.uniqueIndex;
import static org.jclouds.aws.ec2.options.DescribeImagesOptions.Builder.imageIds;
import static org.jclouds.aws.ec2.options.DescribeImagesOptions.Builder.ownedBy;
import static org.jclouds.aws.ec2.reference.EC2Constants.PROPERTY_EC2_AMI_OWNERS;
import static org.jclouds.aws.ec2.reference.EC2Constants.PROPERTY_EC2_CC_AMIs;
import java.net.URI;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import javax.annotation.Resource;
import javax.inject.Inject;
@ -70,6 +69,8 @@ import org.jclouds.logging.Logger;
import com.google.common.base.Function;
import com.google.common.base.Predicates;
import com.google.common.base.Supplier;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableMap.Builder;
/**
*
@ -81,7 +82,7 @@ public class RegionAndNameToImageSupplier implements Supplier<Map<RegionAndName,
@Named(ComputeServiceConstants.COMPUTE_LOGGER)
protected Logger logger = Logger.NULL;
private final Map<String, URI> regionMap;
private final Set<String> regions;
private final DescribeImagesParallel describer;
private final String[] ccAmis;
private final String[] amiOwners;
@ -89,10 +90,10 @@ public class RegionAndNameToImageSupplier implements Supplier<Map<RegionAndName,
private final Map<RegionAndName, Image> images;
@Inject
RegionAndNameToImageSupplier(@Region Map<String, URI> regionMap, DescribeImagesParallel describer,
RegionAndNameToImageSupplier(@Region Set<String> regions, DescribeImagesParallel describer,
@Named(PROPERTY_EC2_CC_AMIs) String[] ccAmis, @Named(PROPERTY_EC2_AMI_OWNERS) final String[] amiOwners,
final ImageParser parser, final Map<RegionAndName, Image> images) {
this.regionMap = regionMap;
this.regions = regions;
this.describer = describer;
this.ccAmis = ccAmis;
this.amiOwners = amiOwners;
@ -108,7 +109,7 @@ public class RegionAndNameToImageSupplier implements Supplier<Map<RegionAndName,
logger.debug(">> providing images");
Iterable<Entry<String, DescribeImagesOptions>> queries = concat(
getDescribeQueriesForOwnersInRegions(regionMap, amiOwners).entrySet(), ccAmisToDescribeQueries(ccAmis)
getDescribeQueriesForOwnersInRegions(regions, amiOwners).entrySet(), ccAmisToDescribeQueries(ccAmis)
.entrySet());
Iterable<? extends Image> parsedImages = filter(transform(describer.apply(queries), parser),
@ -136,16 +137,13 @@ public class RegionAndNameToImageSupplier implements Supplier<Map<RegionAndName,
return queries;
}
private static Map<String, DescribeImagesOptions> getDescribeQueriesForOwnersInRegions(Map<String, URI> regionMap,
private static Map<String, DescribeImagesOptions> getDescribeQueriesForOwnersInRegions(Set<String> regions,
final String[] amiOwners) {
final DescribeImagesOptions options = getOptionsForOwners(amiOwners);
return transformValues(regionMap, new Function<URI, DescribeImagesOptions>() {
@Override
public DescribeImagesOptions apply(URI from) {
return options;
}
});
Builder<String, DescribeImagesOptions> builder = ImmutableMap.<String, DescribeImagesOptions> builder();
for (String region : regions)
builder.put(region, options);
return builder.build();
}
private static DescribeImagesOptions getOptionsForOwners(final String[] amiOwners) {

View File

@ -21,10 +21,12 @@ package org.jclouds.aws.ec2.config;
import java.net.URI;
import java.util.Map;
import java.util.Map.Entry;
import javax.inject.Inject;
import javax.inject.Singleton;
import org.jclouds.aws.config.AWSFormSigningRestClientModule;
import org.jclouds.aws.config.WithZonesFormSigningRestClientModule;
import org.jclouds.aws.ec2.EC2AsyncClient;
import org.jclouds.aws.ec2.EC2Client;
import org.jclouds.aws.ec2.domain.AvailabilityZoneInfo;
@ -50,12 +52,11 @@ import org.jclouds.aws.ec2.services.WindowsAsyncClient;
import org.jclouds.aws.ec2.services.WindowsClient;
import org.jclouds.http.RequiresHttp;
import org.jclouds.location.Region;
import org.jclouds.location.Zone;
import org.jclouds.rest.ConfiguresRestClient;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Maps;
import com.google.inject.Injector;
import com.google.inject.Provides;
import com.google.common.collect.ImmutableMap.Builder;
/**
* Configures the EC2 connection.
@ -64,56 +65,76 @@ import com.google.inject.Provides;
*/
@RequiresHttp
@ConfiguresRestClient
public class EC2RestClientModule extends AWSFormSigningRestClientModule<EC2Client, EC2AsyncClient> {
public class EC2RestClientModule extends WithZonesFormSigningRestClientModule<EC2Client, EC2AsyncClient> {
public static final Map<Class<?>, Class<?>> DELEGATE_MAP = ImmutableMap.<Class<?>, Class<?>> builder()//
.put(AMIClient.class, AMIAsyncClient.class)//
.put(ElasticIPAddressClient.class, ElasticIPAddressAsyncClient.class)//
.put(InstanceClient.class, InstanceAsyncClient.class)//
.put(KeyPairClient.class, KeyPairAsyncClient.class)//
.put(SecurityGroupClient.class, SecurityGroupAsyncClient.class)//
.put(PlacementGroupClient.class, PlacementGroupAsyncClient.class)//
.put(MonitoringClient.class, MonitoringAsyncClient.class)//
.put(WindowsClient.class, WindowsAsyncClient.class)//
.put(AvailabilityZoneAndRegionClient.class, AvailabilityZoneAndRegionAsyncClient.class)//
.put(ElasticBlockStoreClient.class, ElasticBlockStoreAsyncClient.class)//
.build();
.put(AMIClient.class, AMIAsyncClient.class)//
.put(ElasticIPAddressClient.class, ElasticIPAddressAsyncClient.class)//
.put(InstanceClient.class, InstanceAsyncClient.class)//
.put(KeyPairClient.class, KeyPairAsyncClient.class)//
.put(SecurityGroupClient.class, SecurityGroupAsyncClient.class)//
.put(PlacementGroupClient.class, PlacementGroupAsyncClient.class)//
.put(MonitoringClient.class, MonitoringAsyncClient.class)//
.put(WindowsClient.class, WindowsAsyncClient.class)//
.put(AvailabilityZoneAndRegionClient.class, AvailabilityZoneAndRegionAsyncClient.class)//
.put(ElasticBlockStoreClient.class, ElasticBlockStoreAsyncClient.class)//
.build();
public EC2RestClientModule() {
super(EC2Client.class, EC2AsyncClient.class, DELEGATE_MAP);
}
private RuntimeException regionException = null;
@Override
protected Map<String, URI> provideRegions(Injector injector) {
// http://code.google.com/p/google-guice/issues/detail?id=483
// guice doesn't remember when singleton providers throw exceptions.
// in this case, if describeRegions fails, it is called again for
// each provider method that depends on it. To short-circuit this,
// we remember the last exception trusting that guice is single-threaded
if (regionException != null)
throw regionException;
EC2Client client = injector.getInstance(EC2Client.class);
try {
return client.getAvailabilityZoneAndRegionServices().describeRegions();
} catch (RuntimeException e) {
this.regionException = e;
throw e;
}
protected void bindRegionsToProvider() {
bindRegionsToProvider(RegionIdsToURI.class);
}
@Override
protected void bindZonesToProvider() {
bindZonesToProvider(RegionIdToZoneId.class);
}
@Provides
@Singleton
protected Map<String, String> provideAvailabilityZoneToRegions(EC2Client client, @Region Map<String, URI> regions) {
Map<String, String> map = Maps.newHashMap();
for (String region : regions.keySet()) {
for (AvailabilityZoneInfo zoneInfo : client.getAvailabilityZoneAndRegionServices()
.describeAvailabilityZonesInRegion(region)) {
map.put(zoneInfo.getZone(), region);
}
public static class RegionIdsToURI implements javax.inject.Provider<Map<String, URI>> {
private final AvailabilityZoneAndRegionClient client;
@Inject
public RegionIdsToURI(EC2Client client) {
this.client = client.getAvailabilityZoneAndRegionServices();
}
return map;
@Singleton
@Region
@Override
public Map<String, URI> get() {
return client.describeRegions();
}
}
@Singleton
public static class RegionIdToZoneId implements javax.inject.Provider<Map<String, String>> {
private final AvailabilityZoneAndRegionClient client;
private final Map<String, URI> regions;
@Inject
public RegionIdToZoneId(EC2Client client, @Region Map<String, URI> regions) {
this.client = client.getAvailabilityZoneAndRegionServices();
this.regions = regions;
}
@Singleton
@Zone
@Override
public Map<String, String> get() {
Builder<String, String> map = ImmutableMap.<String, String> builder();
for (Entry<String, URI> region : regions.entrySet()) {
for (AvailabilityZoneInfo zoneInfo : client.describeAvailabilityZonesInRegion(region.getKey())) {
map.put(zoneInfo.getZone(), region.getKey());
}
}
return map.build();
}
}
}

View File

@ -37,7 +37,6 @@ import org.jclouds.aws.ec2.domain.Attachment;
import org.jclouds.aws.ec2.domain.Permission;
import org.jclouds.aws.ec2.domain.Snapshot;
import org.jclouds.aws.ec2.domain.Volume;
import org.jclouds.aws.ec2.functions.AvailabilityZoneToEndpoint;
import org.jclouds.aws.ec2.functions.ReturnVoidOnVolumeAvailable;
import org.jclouds.aws.ec2.options.CreateSnapshotOptions;
import org.jclouds.aws.ec2.options.DescribeSnapshotsOptions;
@ -50,6 +49,7 @@ import org.jclouds.aws.ec2.xml.PermissionHandler;
import org.jclouds.aws.ec2.xml.SnapshotHandler;
import org.jclouds.aws.filters.FormSigner;
import org.jclouds.location.functions.RegionToEndpointOrProviderIfNull;
import org.jclouds.location.functions.ZoneToEndpoint;
import org.jclouds.rest.annotations.BinderParam;
import org.jclouds.rest.annotations.EndpointParam;
import org.jclouds.rest.annotations.ExceptionParser;
@ -80,7 +80,7 @@ public interface ElasticBlockStoreAsyncClient {
@FormParams(keys = ACTION, values = "CreateVolume")
@XMLResponseParser(CreateVolumeResponseHandler.class)
ListenableFuture<Volume> createVolumeFromSnapshotInAvailabilityZone(
@EndpointParam(parser = AvailabilityZoneToEndpoint.class) @FormParam("AvailabilityZone") String availabilityZone,
@EndpointParam(parser = ZoneToEndpoint.class) @FormParam("AvailabilityZone") String availabilityZone,
@FormParam("SnapshotId") String snapshotId);
/**
@ -91,7 +91,7 @@ public interface ElasticBlockStoreAsyncClient {
@FormParams(keys = ACTION, values = "CreateVolume")
@XMLResponseParser(CreateVolumeResponseHandler.class)
ListenableFuture<Volume> createVolumeFromSnapshotInAvailabilityZone(
@EndpointParam(parser = AvailabilityZoneToEndpoint.class) @FormParam("AvailabilityZone") String availabilityZone,
@EndpointParam(parser = ZoneToEndpoint.class) @FormParam("AvailabilityZone") String availabilityZone,
@FormParam("Size") int size, @FormParam("SnapshotId") String snapshotId);
/**
@ -102,7 +102,7 @@ public interface ElasticBlockStoreAsyncClient {
@FormParams(keys = ACTION, values = "CreateVolume")
@XMLResponseParser(CreateVolumeResponseHandler.class)
ListenableFuture<Volume> createVolumeInAvailabilityZone(
@EndpointParam(parser = AvailabilityZoneToEndpoint.class) @FormParam("AvailabilityZone") String availabilityZone,
@EndpointParam(parser = ZoneToEndpoint.class) @FormParam("AvailabilityZone") String availabilityZone,
@FormParam("Size") int size);
/**

View File

@ -36,15 +36,20 @@ import org.jclouds.logging.Logger;
* @author Adrian Cole
*/
public class AttachmentHandler extends ParseSax.HandlerForGeneratedRequestWithResult<Attachment> {
private StringBuilder currentText = new StringBuilder();
@Resource
protected Logger logger = Logger.NULL;
protected final DateService dateService;
protected final String defaultRegion;
@Inject
protected DateService dateService;
@Inject
@Region
String defaultRegion;
AttachmentHandler(DateService dateService, @Region String defaultRegion) {
this.dateService = dateService;
this.defaultRegion = defaultRegion;
}
private StringBuilder currentText = new StringBuilder();
private String volumeId;
private String instanceId;
private String device;

View File

@ -35,6 +35,7 @@ import org.jclouds.date.DateService;
import org.jclouds.http.HttpRequest;
import org.jclouds.http.functions.ParseSax;
import org.jclouds.location.Region;
import org.jclouds.location.Zone;
import org.jclouds.logging.Logger;
import org.xml.sax.Attributes;
@ -56,6 +57,7 @@ public class CreateVolumeResponseHandler extends
@Region
String defaultRegion;
@Inject
@Zone
protected Map<String, String> availabilityZoneToRegion;
private String id;

View File

@ -93,7 +93,7 @@ public class ParseAWSErrorFromXmlContent implements HttpErrorHandler {
&& (error.getCode().equals("UnsupportedOperation")))
exception = new UnsupportedOperationException(message, exception);
if (error != null && error.getCode() != null
&& (error.getCode().endsWith(".NotFound") || error.getCode().endsWith(".Unknown")))
&& (error.getCode().endsWith("NotFound") || error.getCode().endsWith(".Unknown")))
exception = new ResourceNotFoundException(message, exception);
else if ((error != null && error.getCode() != null && (error.getCode().equals("IncorrectState") || error
.getCode().endsWith(".Duplicate"))) || (message != null && (message.indexOf("already exists") != -1)))

View File

@ -25,8 +25,7 @@ package org.jclouds.aws.reference;
* @author Adrian Cole
*/
public interface AWSConstants {
public static final String PROPERTY_REGIONS = "jclouds.aws.regions";
public static final String PROPERTY_DEFAULT_REGIONS = "jclouds.aws.default_regions";
public static final String PROPERTY_ZONECLIENT_ENDPOINT = "jclouds.aws.zoneclient-endpoint";
public static final String PROPERTY_AUTH_TAG = "jclouds.aws.auth.tag";
public static final String PROPERTY_HEADER_TAG = "jclouds.aws.header.tag";
}

View File

@ -21,9 +21,8 @@ package org.jclouds.aws.s3;
import static org.jclouds.Constants.PROPERTY_ENDPOINT;
import static org.jclouds.aws.reference.AWSConstants.PROPERTY_AUTH_TAG;
import static org.jclouds.aws.reference.AWSConstants.PROPERTY_DEFAULT_REGIONS;
import static org.jclouds.aws.reference.AWSConstants.PROPERTY_HEADER_TAG;
import static org.jclouds.aws.reference.AWSConstants.PROPERTY_REGIONS;
import static org.jclouds.location.reference.LocationConstants.PROPERTY_REGIONS;
import java.util.Properties;
@ -44,7 +43,6 @@ public class GoogleStoragePropertiesBuilder extends S3PropertiesBuilder {
@Override
protected Properties addEndpoints(Properties properties) {
properties.setProperty(PROPERTY_REGIONS, "GoogleStorage");
properties.setProperty(PROPERTY_DEFAULT_REGIONS, "GoogleStorage");
properties.setProperty(PROPERTY_ENDPOINT, "https://commondatastorage.googleapis.com");
properties.setProperty(PROPERTY_ENDPOINT + ".GoogleStorage",
"https://commondatastorage.googleapis.com");

View File

@ -23,14 +23,13 @@ import static org.jclouds.Constants.PROPERTY_API_VERSION;
import static org.jclouds.Constants.PROPERTY_ENDPOINT;
import static org.jclouds.Constants.PROPERTY_RELAX_HOSTNAME;
import static org.jclouds.aws.reference.AWSConstants.PROPERTY_AUTH_TAG;
import static org.jclouds.aws.reference.AWSConstants.PROPERTY_DEFAULT_REGIONS;
import static org.jclouds.aws.reference.AWSConstants.PROPERTY_HEADER_TAG;
import static org.jclouds.aws.reference.AWSConstants.PROPERTY_REGIONS;
import static org.jclouds.aws.s3.reference.S3Constants.PROPERTY_S3_SERVICE_PATH;
import static org.jclouds.aws.s3.reference.S3Constants.PROPERTY_S3_VIRTUAL_HOST_BUCKETS;
import static org.jclouds.blobstore.reference.BlobStoreConstants.DIRECTORY_SUFFIX_FOLDER;
import static org.jclouds.blobstore.reference.BlobStoreConstants.PROPERTY_BLOBSTORE_DIRECTORY_SUFFIX;
import static org.jclouds.blobstore.reference.BlobStoreConstants.PROPERTY_USER_METADATA_PREFIX;
import static org.jclouds.location.reference.LocationConstants.PROPERTY_REGIONS;
import java.util.Properties;
@ -62,7 +61,6 @@ public class S3PropertiesBuilder extends PropertiesBuilder {
protected Properties addEndpoints(Properties properties) {
properties.setProperty(PROPERTY_REGIONS,
Joiner.on(',').join(Region.US_STANDARD, Region.US_WEST_1, "EU", Region.AP_SOUTHEAST_1));
properties.setProperty(PROPERTY_DEFAULT_REGIONS, Region.US_STANDARD);
properties.setProperty(PROPERTY_ENDPOINT, "https://s3.amazonaws.com");
properties.setProperty(PROPERTY_ENDPOINT + "." + Region.US_STANDARD, "https://s3.amazonaws.com");
properties.setProperty(PROPERTY_ENDPOINT + "." + Region.US_WEST_1, "https://s3-us-west-1.amazonaws.com");

View File

@ -21,10 +21,9 @@ package org.jclouds.aws.s3;
import static org.jclouds.Constants.PROPERTY_API_VERSION;
import static org.jclouds.Constants.PROPERTY_ENDPOINT;
import static org.jclouds.aws.reference.AWSConstants.PROPERTY_DEFAULT_REGIONS;
import static org.jclouds.aws.reference.AWSConstants.PROPERTY_REGIONS;
import static org.jclouds.aws.s3.reference.S3Constants.PROPERTY_S3_SERVICE_PATH;
import static org.jclouds.aws.s3.reference.S3Constants.PROPERTY_S3_VIRTUAL_HOST_BUCKETS;
import static org.jclouds.location.reference.LocationConstants.PROPERTY_REGIONS;
import java.util.Properties;
@ -37,7 +36,6 @@ public class WalrusPropertiesBuilder extends S3PropertiesBuilder {
@Override
protected Properties addEndpoints(Properties properties) {
properties.setProperty(PROPERTY_REGIONS, "Walrus");
properties.setProperty(PROPERTY_DEFAULT_REGIONS, "Walrus");
properties.setProperty(PROPERTY_API_VERSION, "Walrus-1.6");
properties.setProperty(PROPERTY_ENDPOINT, "http://ecc.eucalyptus.com:8773/services/Walrus");
properties.setProperty(PROPERTY_ENDPOINT + ".Walrus",

View File

@ -20,23 +20,18 @@
package org.jclouds.aws.s3.functions;
import static com.google.common.base.Preconditions.checkArgument;
import static org.jclouds.aws.reference.AWSConstants.PROPERTY_DEFAULT_REGIONS;
import static org.jclouds.aws.reference.AWSConstants.PROPERTY_REGIONS;
import java.util.Set;
import javax.annotation.Resource;
import javax.inject.Inject;
import javax.inject.Named;
import javax.inject.Singleton;
import javax.ws.rs.core.MediaType;
import org.jclouds.aws.domain.Region;
import org.jclouds.http.HttpRequest;
import org.jclouds.logging.Logger;
import org.jclouds.rest.binders.BindToStringPayload;
import com.google.common.base.Splitter;
import com.google.common.collect.Iterables;
/**
*
* Depending on your latency and legal requirements, you can specify a location constraint that will
@ -50,34 +45,30 @@ public class BindRegionToXmlPayload extends BindToStringPayload {
@Resource
protected Logger logger = Logger.NULL;
private final Iterable<String> defaultRegions;
private final Iterable<String> regions;
private final String defaultRegion;
private final Set<String> regions;
@Inject
BindRegionToXmlPayload(@Named(PROPERTY_DEFAULT_REGIONS) String defaultRegions,
@Named(PROPERTY_REGIONS) String regions) {
this.defaultRegions = Splitter.on(',').split(defaultRegions);
this.regions = Splitter.on(',').split(regions);
BindRegionToXmlPayload(@org.jclouds.location.Region String defaultRegion,
@org.jclouds.location.Region Set<String> regions) {
this.defaultRegion = defaultRegion;
this.regions = regions;
}
@Override
public <R extends HttpRequest> R bindToRequest(R request, Object input) {
input = input == null ? Iterables.get(defaultRegions, 0) : input;
input = input == null ? defaultRegion : input;
checkArgument(input instanceof String, "this binder is only valid for Region!");
String constraint = (String) input;
String value = null;
if (Iterables.contains(defaultRegions, constraint)) {
if (defaultRegion.equals(constraint)) {
// nothing to bind as this is default.
return request;
} else if (Iterables.contains(regions, constraint)) {
} else if (regions.contains(constraint)) {
value = constraint;
} else {
if (constraint.equals(Region.EU_WEST_1)) {
value = "EU";
} else {
logger.warn("region %s not in %s ", constraint, regions);
value = constraint;
}
logger.warn("region %s not in %s ", constraint, regions);
value = constraint;
}
String payload = String
.format(

View File

@ -23,7 +23,7 @@ import static org.jclouds.Constants.PROPERTY_API_VERSION;
import static org.jclouds.Constants.PROPERTY_ENDPOINT;
import static org.jclouds.aws.reference.AWSConstants.PROPERTY_AUTH_TAG;
import static org.jclouds.aws.reference.AWSConstants.PROPERTY_HEADER_TAG;
import static org.jclouds.aws.reference.AWSConstants.PROPERTY_REGIONS;
import static org.jclouds.location.reference.LocationConstants.PROPERTY_REGIONS;
import java.util.Properties;

View File

@ -19,7 +19,7 @@
package org.jclouds.aws.sqs.config;
import org.jclouds.aws.config.AWSFormSigningRestClientModule;
import org.jclouds.aws.config.FormSigningRestClientModule;
import org.jclouds.aws.sqs.SQSAsyncClient;
import org.jclouds.aws.sqs.SQSClient;
import org.jclouds.http.RequiresHttp;
@ -32,7 +32,7 @@ import org.jclouds.rest.ConfiguresRestClient;
*/
@RequiresHttp
@ConfiguresRestClient
public class SQSRestClientModule extends AWSFormSigningRestClientModule<SQSClient, SQSAsyncClient> {
public class SQSRestClientModule extends FormSigningRestClientModule<SQSClient, SQSAsyncClient> {
public SQSRestClientModule() {
super(SQSClient.class, SQSAsyncClient.class);

View File

@ -34,7 +34,8 @@ import com.google.common.collect.ImmutableBiMap;
/**
*
* @see <a href="http://docs.amazonwebservices.com/AWSSimpleQueueService/latest/APIReference/Query_QueryListQueues.html"
* @see <a href=
* "http://docs.amazonwebservices.com/AWSSimpleQueueService/latest/APIReference/Query_QueryListQueues.html"
* />
* @author Adrian Cole
*/
@ -49,7 +50,7 @@ public class QueueHandler extends ParseSax.HandlerWithResult<Queue> {
@Inject
QueueHandler(Provider<UriBuilder> uriBuilderProvider, @Region Map<String, URI> regionMap) {
this.uriBuilderProvider = uriBuilderProvider;
this.regionBiMap = ImmutableBiMap.<String, URI> builder().putAll(regionMap).build();
this.regionBiMap = ImmutableBiMap.<String, URI> copyOf(regionMap);
}
public Queue getResult() {

View File

@ -38,7 +38,6 @@ public class ProvidersInPropertiesTest {
public void testSupportedComputeServiceProviders() {
Iterable<String> providers = ComputeServiceUtils.getSupportedProviders();
assert !Iterables.contains(providers, "sqs") : providers;
assert !Iterables.contains(providers, "elb") : providers;
assert !Iterables.contains(providers, "s3") : providers;
assert !Iterables.contains(providers, "walrus") : providers;
assert !Iterables.contains(providers, "googlestorage") : providers;
@ -51,7 +50,6 @@ public class ProvidersInPropertiesTest {
public void testSupportedProviders() {
Iterable<String> providers = Providers.getSupportedProviders();
assert Iterables.contains(providers, "sqs") : providers;
assert Iterables.contains(providers, "elb") : providers;
assert Iterables.contains(providers, "s3") : providers;
assert Iterables.contains(providers, "walrus") : providers;
assert Iterables.contains(providers, "googlestorage") : providers;
@ -64,7 +62,6 @@ public class ProvidersInPropertiesTest {
public void testSupportedBlobStoreProviders() {
Iterable<String> providers = BlobStoreUtils.getSupportedProviders();
assert !Iterables.contains(providers, "sqs") : providers;
assert !Iterables.contains(providers, "elb") : providers;
assert Iterables.contains(providers, "s3") : providers;
assert Iterables.contains(providers, "walrus") : providers;
assert Iterables.contains(providers, "googlestorage") : providers;

View File

@ -36,11 +36,11 @@ import com.google.common.collect.ImmutableMap;
* @author Adrian Cole
*/
@Test(sequential = true, groups = { "unit" })
public class AWSRestClientModuleTest {
public class AWSWithZonesFormSigningRestClientModuleTest {
@Test
public void testDefaultRegionWhenThereIsAMatch() {
AWSRestClientModule<EC2Client, EC2AsyncClient> module = new AWSRestClientModule<EC2Client, EC2AsyncClient>(
AWSRestClientModule<EC2Client, EC2AsyncClient> module = new WithZonesFormSigningRestClientModule<EC2Client, EC2AsyncClient>(
EC2Client.class, EC2AsyncClient.class);
URI currentEndpoint = URI.create("http://region1");
@ -51,7 +51,7 @@ public class AWSRestClientModuleTest {
@Test
public void testDefaultRegionWhenThereIsNoMatch() {
AWSRestClientModule<EC2Client, EC2AsyncClient> module = new AWSRestClientModule<EC2Client, EC2AsyncClient>(
AWSRestClientModule<EC2Client, EC2AsyncClient> module = new WithZonesFormSigningRestClientModule<EC2Client, EC2AsyncClient>(
EC2Client.class, EC2AsyncClient.class);
URI currentEndpoint = URI.create("http://region3");

View File

@ -26,11 +26,7 @@ import java.net.URI;
import java.util.Map;
import java.util.Properties;
import javax.inject.Named;
import org.jclouds.Constants;
import org.jclouds.aws.domain.Region;
import org.jclouds.aws.ec2.EC2Client;
import org.jclouds.aws.ec2.config.EC2RestClientModule;
import org.jclouds.aws.ec2.domain.AvailabilityZone;
import org.jclouds.aws.filters.FormSigner;
@ -45,7 +41,6 @@ import org.testng.annotations.BeforeTest;
import org.testng.annotations.Test;
import com.google.common.collect.ImmutableMap;
import com.google.inject.Injector;
import com.google.inject.Module;
/**
@ -58,22 +53,32 @@ public abstract class BaseEC2AsyncClientTest<T> extends RestClientTest<T> {
protected static class StubEC2RestClientModule extends EC2RestClientModule {
@Override
protected String provideTimeStamp(final DateService dateService,
@Named(Constants.PROPERTY_SESSION_INTERVAL) final int expiration) {
protected String provideTimeStamp(DateService dateService, int expiration) {
return "2009-11-08T15:54:08.897Z";
}
@Override
protected Map<String, URI> provideRegions(Injector client) {
return ImmutableMap.<String, URI> of(Region.EU_WEST_1, URI.create("https://ec2.eu-west-1.amazonaws.com"),
Region.US_EAST_1, URI.create("https://ec2.us-east-1.amazonaws.com"), Region.US_WEST_1,
URI.create("https://ec2.us-west-1.amazonaws.com"));
protected void bindRegionsToProvider() {
bindRegionsToProvider(Regions.class);
}
@Override
protected Map<String, String> provideAvailabilityZoneToRegions(EC2Client client,
@org.jclouds.location.Region Map<String, URI> regions) {
return ImmutableMap.<String, String> of(AvailabilityZone.US_EAST_1A, Region.US_EAST_1);
static class Regions implements javax.inject.Provider<Map<String, URI>> {
@Override
public Map<String, URI> get() {
return ImmutableMap.<String, URI> of(Region.EU_WEST_1, URI.create("https://ec2.eu-west-1.amazonaws.com"),
Region.US_EAST_1, URI.create("https://ec2.us-east-1.amazonaws.com"), Region.US_WEST_1,
URI.create("https://ec2.us-west-1.amazonaws.com"));
}
}
protected void bindZonesToProvider() {
bindZonesToProvider(Zones.class);
}
static class Zones implements javax.inject.Provider<Map<String, String>> {
@Override
public Map<String, String> get() {
return ImmutableMap.<String, String> of(AvailabilityZone.US_EAST_1A, Region.US_EAST_1);
}
}
}

View File

@ -28,6 +28,7 @@ import org.jclouds.aws.ec2.domain.AvailabilityZone;
import org.jclouds.http.functions.BaseHandlerTest;
import org.jclouds.http.functions.ParseSax;
import org.jclouds.http.functions.config.SaxParserModule;
import org.jclouds.location.Zone;
import org.testng.annotations.BeforeTest;
import org.testng.annotations.Test;
@ -65,6 +66,7 @@ public class BaseEC2HandlerTest extends BaseHandlerTest {
@SuppressWarnings("unused")
@Singleton
@Provides
@Zone
Map<String, String> provideAvailabilityZoneRegionMap() {
return ImmutableMap.<String, String> of(AvailabilityZone.US_EAST_1A, Region.US_EAST_1);
}

View File

@ -1,118 +0,0 @@
/**
*
* 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.
* ====================================================================
*/
package org.jclouds.aws.elb;
import static org.testng.Assert.assertEquals;
import java.io.IOException;
import java.lang.reflect.Method;
import java.util.Properties;
import javax.inject.Named;
import org.jclouds.Constants;
import org.jclouds.aws.elb.config.ELBRestClientModule;
import org.jclouds.aws.elb.xml.RegisterInstancesWithLoadBalancerResponseHandler;
import org.jclouds.aws.filters.FormSigner;
import org.jclouds.date.DateService;
import org.jclouds.http.HttpRequest;
import org.jclouds.http.RequiresHttp;
import org.jclouds.http.functions.ParseSax;
import org.jclouds.rest.ConfiguresRestClient;
import org.jclouds.rest.RestClientTest;
import org.jclouds.rest.RestContextFactory;
import org.jclouds.rest.RestContextSpec;
import org.jclouds.rest.internal.RestAnnotationProcessor;
import org.testng.annotations.Test;
import com.google.inject.Module;
import com.google.inject.TypeLiteral;
/**
* Tests behavior of {@code ELBAsyncClient}
*
* @author Adrian Cole
*/
// NOTE:without testName, this will not call @Before* and fail w/NPE during surefire
@Test(groups = "unit", testName = "ELBAsyncClientTest")
public class ELBAsyncClientTest extends RestClientTest<ELBAsyncClient> {
public void testRegisterInstancesWithLoadBalancer() throws SecurityException,
NoSuchMethodException, IOException {
Method method = ELBAsyncClient.class.getMethod("registerInstancesWithLoadBalancerInRegion",
String.class, String.class, String[].class);
HttpRequest request = processor.createRequest(method, null, "ReferenceAP1", "i-6055fa09");
assertRequestLineEquals(request,
"POST https://elasticloadbalancing.us-east-1.amazonaws.com/ HTTP/1.1");
assertNonPayloadHeadersEqual(request, "Host: elasticloadbalancing.us-east-1.amazonaws.com\n");
assertPayloadEquals(
request,
"Version=2009-11-25&Action=RegisterInstancesWithLoadBalancer&LoadBalancerName=ReferenceAP1&Instances.member.1.InstanceId=i-6055fa09",
"application/x-www-form-urlencoded", false);
assertResponseParserClassEquals(method, request, ParseSax.class);
assertSaxResponseParserClassEquals(method,
RegisterInstancesWithLoadBalancerResponseHandler.class);
assertExceptionParserClassEquals(method, null);
checkFilters(request);
}
@Override
protected TypeLiteral<RestAnnotationProcessor<ELBAsyncClient>> createTypeLiteral() {
return new TypeLiteral<RestAnnotationProcessor<ELBAsyncClient>>() {
};
}
@RequiresHttp
@ConfiguresRestClient
private static final class TestELBRestClientModule extends ELBRestClientModule {
@Override
protected void configure() {
super.configure();
}
@Override
protected String provideTimeStamp(final DateService dateService,
@Named(Constants.PROPERTY_SESSION_INTERVAL) int expiration) {
return "2009-11-08T15:54:08.897Z";
}
}
@Override
protected Module createModule() {
return new TestELBRestClientModule();
}
@Override
public RestContextSpec<?, ?> createContextSpec() {
return new RestContextFactory().createContextSpec("elb", "identity", "credential",
new Properties());
}
@Override
protected void checkFilters(HttpRequest request) {
assertEquals(request.getFilters().size(), 1);
assertEquals(request.getFilters().get(0).getClass(), FormSigner.class);
}
}

View File

@ -57,6 +57,12 @@ public class ParseAWSErrorFromXmlContentTest {
"<Error><Code>Monster.NotFound</Code></Error>", ResourceNotFoundException.class);
}
@Test
public void test400WithLoadBalancerNotFoundSetsResourceNotFoundException() {
assertCodeMakes("GET", URI.create("https://amazonaws.com/foo"), 400, "",
"<Error><Code>LoadBalancerNotFound</Code></Error>", ResourceNotFoundException.class);
}
@Test
public void test400WithUnsupportedCodeMakesUnsupportedOperationException() {
assertCodeMakes("POST", URI.create("https://ec2.us-west-1.amazonaws.com/"), 400, "",

View File

@ -26,6 +26,7 @@ import java.util.concurrent.TimeoutException;
import org.jclouds.util.Throwables2;
import com.google.common.base.Supplier;
/**
*
* @author Adrian Cole
@ -58,4 +59,9 @@ public class RetryOnTimeOutExceptionSupplier<T> implements Supplier<T> {
return null;
}
@Override
public String toString() {
return "RetryOnTimeOutExceptionSupplier(" + delegate + ")";
}
}

View File

@ -0,0 +1,40 @@
/**
*
* 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.
* ====================================================================
*/
package org.jclouds.location;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import javax.inject.Qualifier;
/**
* Related to a Zone-scoped resource.
*
* @author Adrian Cole
*
*/
@Retention(value = RetentionPolicy.RUNTIME)
@Target(value = { ElementType.FIELD, ElementType.PARAMETER, ElementType.METHOD })
@Qualifier
public @interface Zone {
}

View File

@ -17,7 +17,7 @@
* ====================================================================
*/
package org.jclouds.aws.ec2.functions;
package org.jclouds.location.functions;
import java.net.URI;
import java.util.Map;
@ -25,7 +25,7 @@ import java.util.Map;
import javax.inject.Inject;
import javax.inject.Singleton;
import org.jclouds.location.Region;
import org.jclouds.location.Zone;
import com.google.common.base.Function;
@ -34,19 +34,16 @@ import com.google.common.base.Function;
* @author Adrian Cole
*/
@Singleton
public class AvailabilityZoneToEndpoint implements Function<Object, URI> {
private final Map<String, String> availabilityZoneToRegion;
private final Map<String, URI> regionToEndpoint;
public class ZoneToEndpoint implements Function<Object, URI> {
private final Map<String, URI> zoneToEndpoint;
@Inject
public AvailabilityZoneToEndpoint(@Region Map<String, URI> regionToEndpoint,
Map<String, String> availabilityZoneToRegion) {
this.regionToEndpoint = regionToEndpoint;
this.availabilityZoneToRegion = availabilityZoneToRegion;
public ZoneToEndpoint(@Zone Map<String, URI> zoneToEndpoint) {
this.zoneToEndpoint = zoneToEndpoint;
}
public URI apply(Object from) {
return regionToEndpoint.get(availabilityZoneToRegion.get(from));
return zoneToEndpoint.get(from);
}
}

View File

@ -0,0 +1,28 @@
/**
*
* 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.
* ====================================================================
*/
package org.jclouds.location.reference;
/**
*
* @author Adrian Cole
*/
public interface LocationConstants {
public static final String PROPERTY_REGIONS = "jclouds.location.regions";
}

View File

@ -41,37 +41,53 @@ import com.google.common.collect.Iterables;
*/
@Singleton
public class FirstZoneOrRegionMatchingRegionId implements Supplier<Location> {
private final String region;
@Singleton
public static final class IsRegionAndIdEqualsOrIsZoneParentIdEquals implements Predicate<Location> {
private final String region;
@Inject
IsRegionAndIdEqualsOrIsZoneParentIdEquals(@Region String region) {
this.region = checkNotNull(region, "region");
}
@Override
public boolean apply(Location input) {
switch (input.getScope()) {
case ZONE:
return input.getParent().getId().equals(region);
case REGION:
return input.getId().equals(region);
default:
return false;
}
}
@Override
public String toString() {
return "isRegionAndIdEqualsOrIsZoneParentIdEquals(" + region + ")";
}
}
private final IsRegionAndIdEqualsOrIsZoneParentIdEquals matcher;
private final Supplier<Set<? extends Location>> locationsSupplier;
@Inject
FirstZoneOrRegionMatchingRegionId(@Region String region, @Memoized Supplier<Set<? extends Location>> locationsSupplier) {
this.region = checkNotNull(region, "region");
this.locationsSupplier = checkNotNull(locationsSupplier, "locationsSupplier");
FirstZoneOrRegionMatchingRegionId(IsRegionAndIdEqualsOrIsZoneParentIdEquals matcher,
@Memoized Supplier<Set<? extends Location>> locationsSupplier) {
this.matcher = checkNotNull(matcher, "matcher");
this.locationsSupplier = checkNotNull(locationsSupplier, "locationsSupplier");
}
@Override
@Singleton
public Location get() {
Set<? extends Location> locations = locationsSupplier.get();
try {
Location toReturn = Iterables.find(locationsSupplier.get(), new Predicate<Location>() {
@Override
public boolean apply(Location input) {
switch (input.getScope()) {
case ZONE:
return input.getParent().getId().equals(region);
case REGION:
return input.getId().equals(region);
default:
return false;
}
}
});
Location toReturn = Iterables.find(locations, matcher);
return toReturn.getScope() == LocationScope.REGION ? toReturn : toReturn.getParent();
} catch (NoSuchElementException e) {
throw new IllegalStateException(String.format("region: %s not found in %s", region, locationsSupplier));
throw new IllegalStateException(String.format("region %s not found in %s", matcher, locations));
}
}
}

View File

@ -42,25 +42,33 @@ import com.google.common.base.Supplier;
*/
@Singleton
public class OnlyLocationOrFirstZone implements Supplier<Location> {
@Singleton
public static final class IsZone implements Predicate<Location> {
@Override
public boolean apply(Location input) {
return input.getScope() == LocationScope.ZONE;
}
@Override
public String toString() {
return "isZone()";
}
}
private final Supplier<Set<? extends Location>> locationsSupplier;
private final IsZone isZone;
@Inject
OnlyLocationOrFirstZone(@Memoized Supplier<Set<? extends Location>> locationsSupplier) {
OnlyLocationOrFirstZone(@Memoized Supplier<Set<? extends Location>> locationsSupplier, IsZone isZone) {
this.locationsSupplier = checkNotNull(locationsSupplier, "locationsSupplierSupplier");
this.isZone = checkNotNull(isZone, "isZone");
}
@Override
public Location get() {
if (locationsSupplier.get().size() == 1)
return getOnlyElement(locationsSupplier.get());
return find(locationsSupplier.get(), new Predicate<Location>() {
@Override
public boolean apply(Location input) {
return input.getScope() == LocationScope.ZONE;
}
});
return find(locationsSupplier.get(), isZone);
}
}

View File

@ -17,8 +17,9 @@
* ====================================================================
*/
package org.jclouds.aws.ec2.compute.suppliers;
package org.jclouds.location.suppliers;
import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.collect.Maps.uniqueIndex;
import static com.google.common.collect.Sets.newLinkedHashSet;
@ -32,6 +33,7 @@ import org.jclouds.domain.Location;
import org.jclouds.domain.LocationScope;
import org.jclouds.domain.internal.LocationImpl;
import org.jclouds.location.Provider;
import org.jclouds.location.Zone;
import com.google.common.base.Function;
import com.google.common.base.Supplier;
@ -42,21 +44,21 @@ import com.google.common.collect.ImmutableMap;
* @author Adrian Cole
*/
@Singleton
public class EC2LocationSupplier implements Supplier<Set<? extends Location>> {
private final Map<String, String> availabilityZoneToRegionMap;
public class ZoneToRegionToProvider implements Supplier<Set<? extends Location>> {
private final Map<String, String> zoneToRegion;
private final String providerName;
@Inject
EC2LocationSupplier(Map<String, String> availabilityZoneToRegionMap, @Provider String providerName) {
this.availabilityZoneToRegionMap = availabilityZoneToRegionMap;
this.providerName = providerName;
ZoneToRegionToProvider(@Zone Map<String, String> zoneToRegion, @Provider String providerName) {
this.zoneToRegion = checkNotNull(zoneToRegion, "zoneToRegion");
this.providerName = checkNotNull(providerName, "providerName");
}
@Override
public Set<? extends Location> get() {
Location ec2 = new LocationImpl(LocationScope.PROVIDER, providerName, providerName, null);
Set<Location> locations = newLinkedHashSet();
for (String region : newLinkedHashSet(availabilityZoneToRegionMap.values())) {
for (String region : newLinkedHashSet(zoneToRegion.values())) {
locations.add(new LocationImpl(LocationScope.REGION, region, region, ec2));
}
ImmutableMap<String, Location> idToLocation = uniqueIndex(locations, new Function<Location, String>() {
@ -65,9 +67,8 @@ public class EC2LocationSupplier implements Supplier<Set<? extends Location>> {
return from.getId();
}
});
for (String zone : availabilityZoneToRegionMap.keySet()) {
locations.add(new LocationImpl(LocationScope.ZONE, zone, zone, idToLocation.get(availabilityZoneToRegionMap
.get(zone))));
for (String zone : zoneToRegion.keySet()) {
locations.add(new LocationImpl(LocationScope.ZONE, zone, zone, idToLocation.get(zoneToRegion.get(zone))));
}
return locations;
}

View File

@ -48,7 +48,7 @@ public class RetryOnTimeOutButNotOnAuthorizationExceptionSupplier<T> implements
private final Supplier<T> delegate;
public RetryOnTimeOutButNotOnAuthorizationExceptionSupplier(
final AtomicReference<AuthorizationException> authException, long seconds, final Supplier<T> delegate) {
final AtomicReference<AuthorizationException> authException, final long seconds, final Supplier<T> delegate) {
this.delegate = Suppliers.<T> memoizeWithExpiration(new RetryOnTimeOutExceptionSupplier<T>(new Supplier<T>() {
public T get() {
if (authException.get() != null)
@ -65,6 +65,11 @@ public class RetryOnTimeOutButNotOnAuthorizationExceptionSupplier<T> implements
}
}
@Override
public String toString() {
return "memoizeWithExpiration(" + delegate + ", seconds=" + seconds + ")";
}
}), seconds, TimeUnit.SECONDS);
}
@ -73,4 +78,9 @@ public class RetryOnTimeOutButNotOnAuthorizationExceptionSupplier<T> implements
return delegate.get();
}
@Override
public String toString() {
return "RetryOnTimeOutButNotOnAuthorizationExceptionSupplier(" + delegate + ")";
}
}

View File

@ -41,8 +41,8 @@ simpledb.propertiesbuilder=org.jclouds.simpledb.SimpleDBPropertiesBuilder
aws-simpledb.contextbuilder=org.jclouds.simpledb.SimpleDBContextBuilder
aws-simpledb.propertiesbuilder=org.jclouds.aws.simpledb.SimpleDBPropertiesBuilder
elb.contextbuilder=org.jclouds.aws.elb.ELBContextBuilder
elb.propertiesbuilder=org.jclouds.aws.elb.ELBPropertiesBuilder
elb.contextbuilder=org.jclouds.elb.ELBContextBuilder
elb.propertiesbuilder=org.jclouds.elb.ELBPropertiesBuilder
cloudwatch.contextbuilder=org.jclouds.aws.cloudwatch.CloudWatchContextBuilder
cloudwatch.propertiesbuilder=org.jclouds.aws.cloudwatch.CloudWatchPropertiesBuilder

View File

@ -40,6 +40,14 @@ import com.google.inject.ImplementedBy;
@ImplementedBy(BaseLoadBalancerService.class)
public interface LoadBalancerService {
/**
* The list locations command returns all the valid locations for load balancers. A location has
* a scope, which is typically region or zone. A region is a general area, like eu-west, where a
* zone is similar to a datacenter. If a location has a parent, that implies it is within that
* location. For example a location can be a rack, whose parent is likely to be a zone.
*/
Set<? extends Location> listAssignableLocations();
/**
* @return a reference to the context that created this LoadBalancerService.
*/
@ -75,6 +83,8 @@ public interface LoadBalancerService {
void destroyLoadBalancer(String id);
@Beta
Set<String> listLoadBalancers();
Set<? extends LoadBalancerMetadata> listLoadBalancers();
LoadBalancerMetadata getLoadBalancerMetadata(String id);
}

View File

@ -0,0 +1,67 @@
/**
*
* 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.
* ====================================================================
*/
package org.jclouds.loadbalancer;
import javax.annotation.Nullable;
import org.jclouds.compute.domain.NodeMetadata;
import org.jclouds.domain.Location;
/**
* A means of specifying the interface between the {@link LoadBalancerService LoadBalancerServices}
* and a concrete compute cloud implementation, jclouds or otherwise.
*
* @author Adrian Cole
*
*/
public interface LoadBalancerServiceAdapter<B, L> {
/**
*
* @see LoadBalancerService#createLoadBalancerInLocation
*/
B createLoadBalancerInLocation(@Nullable Location location, String loadBalancerName, String protocol,
int loadBalancerPort, int instancePort, Iterable<? extends NodeMetadata> nodes);
/**
*
* @see LoadBalancerService#listAssignableLocations
*/
Iterable<L> listAssignableLocations();
/**
*
* @see LoadBalancerService#getLoadBalancerMetadata
*/
B getLoadBalancer(String id);
/**
*
* @see LoadBalancerService#destroyLoadBalancer
*/
void destroyLoadBalancer(String id);
/**
*
* @see LoadBalancerService#listLoadBalancers
*/
Iterable<B> listLoadBalancers();
}

View File

@ -0,0 +1,91 @@
/**
*
* 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.
* ====================================================================
*/
package org.jclouds.loadbalancer.config;
import static org.jclouds.Constants.PROPERTY_SESSION_INTERVAL;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.atomic.AtomicReference;
import javax.inject.Named;
import javax.inject.Singleton;
import org.jclouds.collect.Memoized;
import org.jclouds.domain.Location;
import org.jclouds.rest.AuthorizationException;
import org.jclouds.rest.suppliers.RetryOnTimeOutButNotOnAuthorizationExceptionSupplier;
import com.google.common.base.Function;
import com.google.common.base.Supplier;
import com.google.common.base.Suppliers;
import com.google.common.collect.Maps;
import com.google.inject.AbstractModule;
import com.google.inject.Provides;
/**
*
* @author Adrian Cole
*/
public abstract class BaseLoadBalancerServiceContextModule extends AbstractModule {
protected AtomicReference<AuthorizationException> authException = new AtomicReference<AuthorizationException>();
@Override
protected void configure() {
}
@Provides
@Singleton
protected Supplier<Map<String, ? extends Location>> provideLocationMap(
@Memoized Supplier<Set<? extends Location>> locations) {
return Suppliers.compose(new Function<Set<? extends Location>, Map<String, ? extends Location>>() {
@Override
public Map<String, ? extends Location> apply(Set<? extends Location> from) {
return Maps.uniqueIndex(from, new Function<Location, String>() {
@Override
public String apply(Location from) {
return from.getId();
}
});
}
}, locations);
}
@Provides
@Singleton
@Memoized
protected Supplier<Set<? extends Location>> supplyLocationCache(@Named(PROPERTY_SESSION_INTERVAL) long seconds,
final Supplier<Set<? extends Location>> locationSupplier) {
return new RetryOnTimeOutButNotOnAuthorizationExceptionSupplier<Set<? extends Location>>(authException, seconds,
new Supplier<Set<? extends Location>>() {
@Override
public Set<? extends Location> get() {
return locationSupplier.get();
}
});
}
}

View File

@ -0,0 +1,66 @@
/**
*
* 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.
* ====================================================================
*/
package org.jclouds.loadbalancer.config;
import org.jclouds.loadbalancer.strategy.DestroyLoadBalancerStrategy;
import org.jclouds.loadbalancer.strategy.GetLoadBalancerMetadataStrategy;
import org.jclouds.loadbalancer.strategy.ListLoadBalancersStrategy;
import org.jclouds.loadbalancer.strategy.LoadBalanceNodesStrategy;
import com.google.inject.AbstractModule;
import com.google.inject.Scopes;
/**
*
* @author Adrian Cole
*
*/
public abstract class BindLoadBalancerStrategiesByClass extends AbstractModule {
protected void configure() {
bindLoadBalanceNodesStrategy(defineLoadBalanceNodesStrategy());
bindListLoadBalancersStrategy(defineListLoadBalancersStrategy());
bindGetLoadBalancerMetadataStrategy(defineGetLoadBalancerMetadataStrategy());
bindDestroyLoadBalancerStrategy(defineDestroyLoadBalancerStrategy());
}
protected void bindLoadBalanceNodesStrategy(Class<? extends LoadBalanceNodesStrategy> clazz) {
bind(LoadBalanceNodesStrategy.class).to(clazz).in(Scopes.SINGLETON);
}
protected void bindDestroyLoadBalancerStrategy(Class<? extends DestroyLoadBalancerStrategy> clazz) {
bind(DestroyLoadBalancerStrategy.class).to(clazz).in(Scopes.SINGLETON);
}
protected void bindGetLoadBalancerMetadataStrategy(Class<? extends GetLoadBalancerMetadataStrategy> clazz) {
bind(GetLoadBalancerMetadataStrategy.class).to(clazz).in(Scopes.SINGLETON);
}
protected void bindListLoadBalancersStrategy(Class<? extends ListLoadBalancersStrategy> clazz) {
bind(ListLoadBalancersStrategy.class).to(clazz).in(Scopes.SINGLETON);
}
protected abstract Class<? extends LoadBalanceNodesStrategy> defineLoadBalanceNodesStrategy();
protected abstract Class<? extends DestroyLoadBalancerStrategy> defineDestroyLoadBalancerStrategy();
protected abstract Class<? extends GetLoadBalancerMetadataStrategy> defineGetLoadBalancerMetadataStrategy();
protected abstract Class<? extends ListLoadBalancersStrategy> defineListLoadBalancersStrategy();
}

View File

@ -0,0 +1,93 @@
/**
*
* 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.
* ====================================================================
*/
package org.jclouds.loadbalancer.config;
import java.util.Set;
import javax.inject.Inject;
import javax.inject.Singleton;
import org.jclouds.compute.domain.Hardware;
import org.jclouds.compute.domain.Image;
import org.jclouds.domain.Location;
import org.jclouds.location.suppliers.OnlyLocationOrFirstZone;
import com.google.common.base.Supplier;
import com.google.inject.AbstractModule;
import com.google.inject.Scopes;
import com.google.inject.TypeLiteral;
/**
* @author Adrian Cole
*/
public abstract class BindLoadBalancerSuppliersByClass extends AbstractModule {
@Override
protected void configure() {
bindLocationSupplier(defineLocationSupplier());
bindDefaultLocationSupplier(defineDefaultLocationSupplier());
}
protected Class<? extends Supplier<Set<? extends Location>>> defineLocationSupplier() {
return SupplierOfLocationSet.class;
}
@Singleton
static class SupplierOfLocationSet implements Supplier<Set<? extends Location>> {
private final Set<? extends Location> locations;
@Inject
SupplierOfLocationSet(Set<? extends Location> locations) {
this.locations = locations;
}
@Override
public Set<? extends Location> get() {
return locations;
}
}
protected Class<? extends Supplier<Location>> defineDefaultLocationSupplier() {
return OnlyLocationOrFirstZone.class;
}
protected void bindImageSupplier(Class<? extends Supplier<Set<? extends Image>>> clazz) {
bind(new TypeLiteral<Supplier<Set<? extends Image>>>() {
}).to(clazz).in(Scopes.SINGLETON);
}
protected void bindLocationSupplier(Class<? extends Supplier<Set<? extends Location>>> clazz) {
bind(new TypeLiteral<Supplier<Set<? extends Location>>>() {
}).to(clazz).in(Scopes.SINGLETON);
}
protected void bindDefaultLocationSupplier(Class<? extends Supplier<Location>> clazz) {
bind(new TypeLiteral<Supplier<Location>>() {
}).to(clazz).in(Scopes.SINGLETON);
}
protected void bindHardwareSupplier(Class<? extends Supplier<Set<? extends Hardware>>> clazz) {
bind(new TypeLiteral<Supplier<Set<? extends Hardware>>>() {
}).to(clazz).in(Scopes.SINGLETON);
}
}

View File

@ -21,25 +21,34 @@ package org.jclouds.loadbalancer.internal;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.collect.Sets.newLinkedHashSet;
import java.util.LinkedHashSet;
import java.util.Set;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicReference;
import javax.annotation.Nullable;
import javax.annotation.Resource;
import javax.inject.Named;
import javax.inject.Singleton;
import org.jclouds.collect.Memoized;
import org.jclouds.compute.domain.NodeMetadata;
import org.jclouds.domain.Location;
import org.jclouds.http.handlers.BackoffLimitedRetryHandler;
import org.jclouds.loadbalancer.LoadBalancerService;
import org.jclouds.loadbalancer.LoadBalancerServiceContext;
import org.jclouds.loadbalancer.domain.LoadBalancerMetadata;
import org.jclouds.loadbalancer.reference.LoadBalancerConstants;
import org.jclouds.loadbalancer.strategy.DestroyLoadBalancerStrategy;
import org.jclouds.loadbalancer.strategy.GetLoadBalancerMetadataStrategy;
import org.jclouds.loadbalancer.strategy.ListLoadBalancersStrategy;
import org.jclouds.loadbalancer.strategy.LoadBalanceNodesStrategy;
import org.jclouds.logging.Logger;
import org.jclouds.predicates.RetryablePredicate;
import com.google.common.collect.ImmutableSet;
import com.google.common.base.Predicate;
import com.google.common.base.Supplier;
import com.google.inject.Inject;
/**
@ -54,23 +63,36 @@ public class BaseLoadBalancerService implements LoadBalancerService {
@Named(LoadBalancerConstants.LOADBALANCER_LOGGER)
protected Logger logger = Logger.NULL;
protected final Supplier<Location> defaultLocationSupplier;
protected final LoadBalancerServiceContext context;
protected final LoadBalanceNodesStrategy loadBalancerStrategy;
protected final GetLoadBalancerMetadataStrategy getLoadBalancerMetadataStrategy;
protected final DestroyLoadBalancerStrategy destroyLoadBalancerStrategy;
// protected final ListLoadBalancersStrategy listLoadBalancersStrategy;
protected final BackoffLimitedRetryHandler backoffLimitedRetryHandler;
protected final ListLoadBalancersStrategy listLoadBalancersStrategy;
protected final Supplier<Set<? extends Location>> locations;
@Inject
protected BaseLoadBalancerService(LoadBalancerServiceContext context, LoadBalanceNodesStrategy loadBalancerStrategy,
DestroyLoadBalancerStrategy destroyLoadBalancerStrategy,
// ListLoadBalancersStrategy listLoadBalancersStrategy,
BackoffLimitedRetryHandler backoffLimitedRetryHandler) {
protected BaseLoadBalancerService(Supplier<Location> defaultLocationSupplier, LoadBalancerServiceContext context,
LoadBalanceNodesStrategy loadBalancerStrategy,
GetLoadBalancerMetadataStrategy getLoadBalancerMetadataStrategy,
DestroyLoadBalancerStrategy destroyLoadBalancerStrategy, ListLoadBalancersStrategy listLoadBalancersStrategy,
@Memoized Supplier<Set<? extends Location>> locations) {
this.defaultLocationSupplier = checkNotNull(defaultLocationSupplier, "defaultLocationSupplier");
this.context = checkNotNull(context, "context");
this.loadBalancerStrategy = checkNotNull(loadBalancerStrategy, "loadBalancerStrategy");
this.getLoadBalancerMetadataStrategy = checkNotNull(getLoadBalancerMetadataStrategy,
"getLoadBalancerMetadataStrategy");
this.destroyLoadBalancerStrategy = checkNotNull(destroyLoadBalancerStrategy, "destroyLoadBalancerStrategy");
// this.listLoadBalancersStrategy = checkNotNull(listLoadBalancersStrategy,
// "listLoadBalancersStrategy");
this.backoffLimitedRetryHandler = checkNotNull(backoffLimitedRetryHandler, "backoffLimitedRetryHandler");
this.listLoadBalancersStrategy = checkNotNull(listLoadBalancersStrategy, "listLoadBalancersStrategy");
this.locations = checkNotNull(locations, "locations");
}
/**
* {@inheritDoc}
*/
@Override
public Set<? extends Location> listAssignableLocations() {
return locations.get();
}
/**
@ -82,18 +104,20 @@ public class BaseLoadBalancerService implements LoadBalancerService {
}
@Override
public LoadBalancerMetadata createLoadBalancerInLocation(Location location, String loadBalancerName,
public LoadBalancerMetadata createLoadBalancerInLocation(@Nullable Location location, String loadBalancerName,
String protocol, int loadBalancerPort, int instancePort, Iterable<? extends NodeMetadata> nodes) {
if (location == null)
location = defaultLocationSupplier.get();
checkNotNull(loadBalancerName, "loadBalancerName");
checkNotNull(protocol, "protocol");
checkArgument(protocol.toUpperCase().equals("HTTP") || protocol.toUpperCase().equals("TCP"),
"Acceptable values for protocol are HTTP or TCP");
logger.debug(">> creating load balancer (%s)", loadBalancerName);
LoadBalancerMetadata lb = loadBalancerStrategy.execute(location, loadBalancerName, protocol, loadBalancerPort,
instancePort, nodes);
LoadBalancerMetadata lb = loadBalancerStrategy.createLoadBalancerInLocation(location, loadBalancerName, protocol,
loadBalancerPort, instancePort, nodes);
logger.debug("<< created load balancer (%s)", loadBalancerName, lb);
return lb;
}
@ -101,18 +125,48 @@ public class BaseLoadBalancerService implements LoadBalancerService {
* {@inheritDoc}
*/
@Override
public void destroyLoadBalancer(String loadBalancer) {
checkNotNull(loadBalancer, "loadBalancer");
logger.debug(">> destroying load balancer(%s)", loadBalancer);
boolean successful = destroyLoadBalancerStrategy.execute(loadBalancer);
logger.debug("<< destroyed load balancer(%s) success(%s)", loadBalancer, successful);
public LoadBalancerMetadata getLoadBalancerMetadata(String id) {
checkNotNull(id, "id");
return getLoadBalancerMetadataStrategy.getLoadBalancer(id);
}
public Set<String> listLoadBalancers() {
return ImmutableSet.of();
// TODO
// Set<String> loadBalancerSet = listLoadBalancersStrategy.execute();
// return loadBalancerSet;
/**
* {@inheritDoc}
*/
@Override
public void destroyLoadBalancer(final String id) {
checkNotNull(id, "id");
logger.debug(">> destroying load balancer(%s)", id);
final AtomicReference<LoadBalancerMetadata> loadBalancer = new AtomicReference<LoadBalancerMetadata>();
RetryablePredicate<String> tester = new RetryablePredicate<String>(new Predicate<String>() {
@Override
public boolean apply(String input) {
try {
LoadBalancerMetadata md = destroyLoadBalancerStrategy.destroyLoadBalancer(id);
if (md != null)
loadBalancer.set(md);
return true;
} catch (IllegalStateException e) {
logger.warn("<< illegal state destroying load balancer(%s)", id);
return false;
}
}
}, 3000, 1000, TimeUnit.MILLISECONDS);// TODO make timeouts class like ComputeServiceconstants
boolean successful = tester.apply(id) && loadBalancer.get() == null; // TODO add load
// balancerTerminated
// retryable predicate
// (load balancer.get() == null ||
// load balancerTerminated.apply(load balancer.get()));
logger.debug("<< destroyed load balancer(%s) success(%s)", id, successful);
}
public Set<? extends LoadBalancerMetadata> listLoadBalancers() {
logger.debug(">> listing load balancers");
LinkedHashSet<LoadBalancerMetadata> set = newLinkedHashSet(listLoadBalancersStrategy.listLoadBalancers());
logger.debug("<< list(%d)", set.size());
return set;
}
}

View File

@ -19,6 +19,8 @@
package org.jclouds.loadbalancer.strategy;
import org.jclouds.loadbalancer.domain.LoadBalancerMetadata;
import com.google.common.annotations.Beta;
/**
@ -29,6 +31,6 @@ import com.google.common.annotations.Beta;
@Beta
public interface DestroyLoadBalancerStrategy {
boolean execute(String loadBalancer);
LoadBalancerMetadata destroyLoadBalancer(String id);
}

View File

@ -0,0 +1,33 @@
/**
*
* 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.
* ====================================================================
*/
package org.jclouds.loadbalancer.strategy;
import org.jclouds.loadbalancer.domain.LoadBalancerMetadata;
/**
* returns all details associated to the node below.
*
* @author Adrian Cole
*/
public interface GetLoadBalancerMetadataStrategy {
LoadBalancerMetadata getLoadBalancer(String id);
}

View File

@ -1,6 +1,6 @@
/**
*
* Copyright (C) 2009 Cloud Conscious, LLC. <info@cloudconscious.com>
* Copyright (C) 2010 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* Licensed under the Apache License, Version 2.0 (the "License");
@ -17,9 +17,9 @@
* ====================================================================
*/
package org.jclouds.compute.strategy;
package org.jclouds.loadbalancer.strategy;
import java.util.Set;
import org.jclouds.loadbalancer.domain.LoadBalancerMetadata;
import com.google.common.annotations.Beta;
@ -31,6 +31,6 @@ import com.google.common.annotations.Beta;
@Beta
public interface ListLoadBalancersStrategy {
Set<String> execute();
Iterable<? extends LoadBalancerMetadata> listLoadBalancers();
}

View File

@ -54,7 +54,7 @@ public interface LoadBalanceNodesStrategy {
* @see org.jclouds.compute.ComputeService
*/
@Beta
LoadBalancerMetadata execute(Location location, String name, String protocol, int loadBalancerPort,
LoadBalancerMetadata createLoadBalancerInLocation(Location location, String name, String protocol, int loadBalancerPort,
int instancePort, Iterable<? extends NodeMetadata> nodes);
}

View File

@ -87,8 +87,8 @@ public abstract class BaseLoadBalancerServiceLiveTest {
credential = System.getProperty("test." + provider + ".credential");
endpoint = System.getProperty("test." + provider + ".endpoint");
apiversion = System.getProperty("test." + provider + ".apiversion");
computeProvider = checkNotNull(System.getProperty("test.compute.provider"), "test.compute.provider");
computeProvider = checkNotNull(System.getProperty("test." + provider + ".compute.provider"), "test." + provider
+ ".compute.provider");
computeIdentity = checkNotNull(System.getProperty("test." + computeProvider + ".identity"), "test."
+ computeProvider + ".identity");
computeCredential = System.getProperty("test." + computeProvider + ".credential");
@ -164,7 +164,7 @@ public abstract class BaseLoadBalancerServiceLiveTest {
abstract protected Module getSshModule();
@BeforeGroups(groups = { "integration", "live" })
@BeforeGroups(groups = { "integration", "live" }, dependsOnMethods = "setupClient")
public void createNodes() throws RunNodesException {
try {
nodes = computeContext.getComputeService().runNodesWithTag(tag, 2);
@ -195,7 +195,7 @@ public abstract class BaseLoadBalancerServiceLiveTest {
@AfterTest
protected void cleanup() throws InterruptedException, ExecutionException, TimeoutException {
if (loadbalancer != null) {
context.getLoadBalancerService().destroyLoadBalancer(tag);
context.getLoadBalancerService().destroyLoadBalancer(loadbalancer.getId());
}
if (nodes != null) {
computeContext.getComputeService().destroyNodesMatching(NodePredicates.withTag(tag));

View File

@ -25,7 +25,7 @@ import static org.jclouds.aws.domain.Region.EU_WEST_1;
import static org.jclouds.aws.domain.Region.US_EAST_1;
import static org.jclouds.aws.domain.Region.US_WEST_1;
import static org.jclouds.aws.reference.AWSConstants.PROPERTY_AUTH_TAG;
import static org.jclouds.aws.reference.AWSConstants.PROPERTY_REGIONS;
import static org.jclouds.location.reference.LocationConstants.PROPERTY_REGIONS;
import java.util.Properties;
import java.util.Set;

View File

@ -21,6 +21,7 @@ package org.jclouds.aws.simpledb;
import static org.jclouds.aws.simpledb.SimpleDBPropertiesBuilder.DEFAULT_REGIONS;
import org.jclouds.simpledb.SimpleDBClientLiveTest;
import org.testng.annotations.Test;
/**
@ -28,11 +29,10 @@ import org.testng.annotations.Test;
*
* @author Adrian Cole
*/
@Test(groups = "live", sequential = true, testName = "aws.SimpleDBClientLiveTest")
public class SimpleDBClientLiveTest extends org.jclouds.simpledb.SimpleDBClientLiveTest {
public SimpleDBClientLiveTest(){
@Test(groups = "live", sequential = true, testName = "AWSSimpleDBClientLiveTest")
public class AWSSimpleDBClientLiveTest extends SimpleDBClientLiveTest {
public AWSSimpleDBClientLiveTest(){
provider = "aws-simpledb";
}
@Test
void testListDomainsInRegion() throws InterruptedException {