diff --git a/apis/cloudloadbalancers/src/main/java/org/jclouds/cloudloadbalancers/config/CloudLoadBalancersRestClientModule.java b/apis/cloudloadbalancers/src/main/java/org/jclouds/cloudloadbalancers/config/CloudLoadBalancersRestClientModule.java index b5550ded5e..3bd986ff3a 100644 --- a/apis/cloudloadbalancers/src/main/java/org/jclouds/cloudloadbalancers/config/CloudLoadBalancersRestClientModule.java +++ b/apis/cloudloadbalancers/src/main/java/org/jclouds/cloudloadbalancers/config/CloudLoadBalancersRestClientModule.java @@ -34,6 +34,7 @@ import org.jclouds.cloudloadbalancers.features.LoadBalancerAsyncClient; import org.jclouds.cloudloadbalancers.features.LoadBalancerClient; import org.jclouds.cloudloadbalancers.features.NodeAsyncClient; import org.jclouds.cloudloadbalancers.features.NodeClient; +import org.jclouds.cloudloadbalancers.functions.ConvertLB; import org.jclouds.cloudloadbalancers.handlers.ParseCloudLoadBalancersErrorFromHttpResponse; import org.jclouds.cloudloadbalancers.reference.RackspaceConstants; import org.jclouds.http.HttpErrorHandler; @@ -63,6 +64,7 @@ import com.google.inject.Injector; import com.google.inject.Provides; import com.google.inject.Scopes; import com.google.inject.TypeLiteral; +import com.google.inject.assistedinject.FactoryModuleBuilder; /** * Configures theRackspace Cloud Load Balancers connection. @@ -109,6 +111,7 @@ public class CloudLoadBalancersRestClientModule extends install(new OpenStackAuthenticationModule()); bind(DateAdapter.class).to(Iso8601DateAdapter.class); bindRegionsToProvider(); + install(new FactoryModuleBuilder().build(ConvertLB.Factory.class)); super.configure(); } diff --git a/apis/cloudloadbalancers/src/main/java/org/jclouds/cloudloadbalancers/domain/LoadBalancer.java b/apis/cloudloadbalancers/src/main/java/org/jclouds/cloudloadbalancers/domain/LoadBalancer.java index e83d2142f5..32ef3908c7 100644 --- a/apis/cloudloadbalancers/src/main/java/org/jclouds/cloudloadbalancers/domain/LoadBalancer.java +++ b/apis/cloudloadbalancers/src/main/java/org/jclouds/cloudloadbalancers/domain/LoadBalancer.java @@ -25,6 +25,7 @@ import java.util.Date; import java.util.Set; import org.jclouds.cloudloadbalancers.domain.internal.BaseLoadBalancer; +import org.jclouds.javax.annotation.Nullable; import com.google.common.collect.ImmutableSet; @@ -75,10 +76,10 @@ public class LoadBalancer extends BaseLoadBalancer { this.status = status; return this; } - + public Builder algorithm(Algorithm algorithm) { - algorithm(algorithm.name()); - return this; + algorithm(algorithm.name()); + return this; } public Builder virtualIPs(Iterable virtualIPs) { @@ -212,51 +213,50 @@ public class LoadBalancer extends BaseLoadBalancer { } } - + /** - All load balancers utilize an algorithm that defines how traffic should be directed between - back-end nodes. The default algorithm for newly created load balancers is RANDOM, which can - be overridden at creation time or changed after the load balancer has been initially - provisioned. The algorithm name is to be constant within a major revision of the load - balancing API, though new algorithms may be created with a unique algorithm name within - a given major revision of the service API. + * All load balancers utilize an algorithm that defines how traffic should be directed between + * back-end nodes. The default algorithm for newly created load balancers is RANDOM, which can be + * overridden at creation time or changed after the load balancer has been initially provisioned. + * The algorithm name is to be constant within a major revision of the load balancing API, though + * new algorithms may be created with a unique algorithm name within a given major revision of + * the service API. */ public static enum Algorithm { /** * The node with the lowest number of connections will receive requests. */ - LEAST_CONNECTIONS, + LEAST_CONNECTIONS, /** * Back-end servers are selected at random. */ - RANDOM, + RANDOM, /** * Connections are routed to each of the back-end servers in turn. */ - ROUND_ROBIN, + ROUND_ROBIN, /** - * Each request will be assigned to a node based on the number of concurrent connections - * to the node and its weight. + * Each request will be assigned to a node based on the number of concurrent connections to + * the node and its weight. */ - WEIGHTED_LEAST_CONNECTIONS, + WEIGHTED_LEAST_CONNECTIONS, /** - * A round robin algorithm, but with different proportions of traffic being directed to - * the back-end nodes. Weights must be defined as part of the load balancer's node configuration. + * A round robin algorithm, but with different proportions of traffic being directed to the + * back-end nodes. Weights must be defined as part of the load balancer's node configuration. */ - WEIGHTED_ROUND_ROBIN, - UNRECOGNIZED; + WEIGHTED_ROUND_ROBIN, UNRECOGNIZED; - public static Algorithm fromValue(String status) { + public static Algorithm fromValue(String algorithm) { try { - return valueOf(checkNotNull(status, "status")); + return valueOf(checkNotNull(algorithm, "algorithm")); } catch (IllegalArgumentException e) { return UNRECOGNIZED; } } } - - public static Algorithm[] WEIGHTED_ALGORITHMS = {Algorithm.WEIGHTED_LEAST_CONNECTIONS, - Algorithm.WEIGHTED_ROUND_ROBIN}; + + public static Algorithm[] WEIGHTED_ALGORITHMS = { Algorithm.WEIGHTED_LEAST_CONNECTIONS, + Algorithm.WEIGHTED_ROUND_ROBIN }; private final String region; private final int id; @@ -269,15 +269,15 @@ public class LoadBalancer extends BaseLoadBalancer { private final Date updated; private final boolean connectionLoggingEnabled; - public LoadBalancer(String region, int id, String name, String protocol, Integer port, String algorithm, Status status, - Iterable virtualIPs, Iterable nodes, String sessionPersistenceType, String clusterName, - Date created, Date updated, boolean connectionLoggingEnabled) { + public LoadBalancer(String region, int id, String name, String protocol, Integer port, @Nullable String algorithm, + Status status, Iterable virtualIPs, Iterable nodes, String sessionPersistenceType, + String clusterName, Date created, Date updated, boolean connectionLoggingEnabled) { super(name, protocol, port, algorithm, nodes); this.region = checkNotNull(region, "region"); checkArgument(id != -1, "id must be specified"); this.id = id; this.status = checkNotNull(status, "status"); - this.algorithm = Algorithm.fromValue(algorithm); + this.algorithm = algorithm != null ? Algorithm.fromValue(algorithm) : null; this.virtualIPs = ImmutableSet.copyOf(checkNotNull(virtualIPs, "virtualIPs")); this.sessionPersistenceType = sessionPersistenceType; this.clusterName = clusterName; @@ -297,9 +297,14 @@ public class LoadBalancer extends BaseLoadBalancer { public Status getStatus() { return status; } - + + /** + * + * @return algorithm, which may be null if the load balancer is deleted + */ + @Nullable public Algorithm getTypedAlgorithm() { - return algorithm; + return algorithm; } public Set getVirtualIPs() { diff --git a/apis/cloudloadbalancers/src/main/java/org/jclouds/cloudloadbalancers/domain/internal/BaseLoadBalancer.java b/apis/cloudloadbalancers/src/main/java/org/jclouds/cloudloadbalancers/domain/internal/BaseLoadBalancer.java index 3d37e287e3..11cc075118 100644 --- a/apis/cloudloadbalancers/src/main/java/org/jclouds/cloudloadbalancers/domain/internal/BaseLoadBalancer.java +++ b/apis/cloudloadbalancers/src/main/java/org/jclouds/cloudloadbalancers/domain/internal/BaseLoadBalancer.java @@ -23,6 +23,8 @@ import static com.google.common.base.Preconditions.checkNotNull; import java.util.Set; import java.util.SortedSet; +import org.jclouds.javax.annotation.Nullable; + import com.google.common.collect.ImmutableSet; import com.google.common.collect.ImmutableSortedSet; import com.google.common.collect.Sets; @@ -107,7 +109,7 @@ public class BaseLoadBalancer, T extends BaseLoadBalancer< // so tests will come out consistently protected SortedSet nodes = ImmutableSortedSet.of(); - public BaseLoadBalancer(String name, String protocol, Integer port, String algorithm, Iterable nodes) { + public BaseLoadBalancer(String name, String protocol, Integer port, @Nullable String algorithm, Iterable nodes) { this.name = checkNotNull(name, "name"); this.protocol = protocol;// null on deleted LB this.port = port;// null on deleted LB @@ -132,6 +134,11 @@ public class BaseLoadBalancer, T extends BaseLoadBalancer< return port; } + /** + * + * @return algorithm, which may be null if the load balancer is deleted + */ + @Nullable public String getAlgorithm() { return algorithm; } diff --git a/apis/cloudloadbalancers/src/main/java/org/jclouds/cloudloadbalancers/functions/ConvertLB.java b/apis/cloudloadbalancers/src/main/java/org/jclouds/cloudloadbalancers/functions/ConvertLB.java index d47397f464..f6030927a3 100644 --- a/apis/cloudloadbalancers/src/main/java/org/jclouds/cloudloadbalancers/functions/ConvertLB.java +++ b/apis/cloudloadbalancers/src/main/java/org/jclouds/cloudloadbalancers/functions/ConvertLB.java @@ -18,39 +18,57 @@ */ package org.jclouds.cloudloadbalancers.functions; +import javax.annotation.Resource; +import javax.inject.Inject; + import org.jclouds.cloudloadbalancers.domain.LoadBalancer; import org.jclouds.cloudloadbalancers.domain.LoadBalancer.Builder; +import org.jclouds.logging.Logger; import com.google.common.base.Function; import com.google.common.collect.Iterables; +import com.google.inject.assistedinject.Assisted; /** * @author Adrian Cole */ public class ConvertLB implements Function { + public static interface Factory { + ConvertLB createForRegion(String region); + } + + @Resource + protected Logger logger = Logger.NULL; + private final String region; - ConvertLB(String region) { + @Inject + ConvertLB(@Assisted String region) { this.region = region.toUpperCase(); } @Override public LoadBalancer apply(LB lb) { - Builder builder = LoadBalancer.builder().region(region).name(lb.getName()).port(lb.getPort()).protocol( - lb.getProtocol()).algorithm(lb.getAlgorithm()).nodes(lb.getNodes()).id(lb.id).status(lb.status) - .virtualIPs(lb.virtualIps); - if (lb.cluster.size() == 1) - builder.clusterName(Iterables.get(lb.cluster.values(), 0)); - if (lb.sessionPersistence.size() == 1) - builder.sessionPersistenceType(Iterables.get(lb.sessionPersistence.values(), 0)); - if (lb.created.size() == 1) - builder.created(Iterables.get(lb.created.values(), 0)); - if (lb.updated.size() == 1) - builder.updated(Iterables.get(lb.updated.values(), 0)); - if (lb.connectionLogging.size() == 1) - builder.connectionLoggingEnabled(Iterables.get(lb.connectionLogging.values(), 0)); - return builder.build(); + try { + Builder builder = LoadBalancer.builder().region(region).name(lb.getName()).port(lb.getPort()).protocol( + lb.getProtocol()).algorithm(lb.getAlgorithm()).nodes(lb.getNodes()).id(lb.id).status(lb.status) + .virtualIPs(lb.virtualIps); + if (lb.cluster.size() == 1) + builder.clusterName(Iterables.get(lb.cluster.values(), 0)); + if (lb.sessionPersistence.size() == 1) + builder.sessionPersistenceType(Iterables.get(lb.sessionPersistence.values(), 0)); + if (lb.created.size() == 1) + builder.created(Iterables.get(lb.created.values(), 0)); + if (lb.updated.size() == 1) + builder.updated(Iterables.get(lb.updated.values(), 0)); + if (lb.connectionLogging.size() == 1) + builder.connectionLoggingEnabled(Iterables.get(lb.connectionLogging.values(), 0)); + return builder.build(); + } catch (NullPointerException e) { + logger.warn(e, "nullpointer found parsing %s", lb); + throw e; + } } } \ No newline at end of file diff --git a/apis/cloudloadbalancers/src/main/java/org/jclouds/cloudloadbalancers/functions/UnwrapLoadBalancer.java b/apis/cloudloadbalancers/src/main/java/org/jclouds/cloudloadbalancers/functions/UnwrapLoadBalancer.java index 08388be8dc..52b66c1cca 100644 --- a/apis/cloudloadbalancers/src/main/java/org/jclouds/cloudloadbalancers/functions/UnwrapLoadBalancer.java +++ b/apis/cloudloadbalancers/src/main/java/org/jclouds/cloudloadbalancers/functions/UnwrapLoadBalancer.java @@ -18,11 +18,15 @@ */ package org.jclouds.cloudloadbalancers.functions; +import static com.google.common.base.Preconditions.checkNotNull; +import static com.google.common.base.Preconditions.checkState; + import java.util.Map; import javax.inject.Inject; import org.jclouds.cloudloadbalancers.domain.LoadBalancer; +import org.jclouds.cloudloadbalancers.functions.ConvertLB.Factory; import org.jclouds.http.HttpRequest; import org.jclouds.http.HttpResponse; import org.jclouds.http.functions.ParseJson; @@ -37,15 +41,19 @@ import com.google.common.collect.Iterables; public class UnwrapLoadBalancer implements Function, InvocationContext { private final ParseJson> json; + private final Factory factory; + private ConvertLB convertLB; @Inject - UnwrapLoadBalancer(ParseJson> json) { - this.json = json; + UnwrapLoadBalancer(ParseJson> json, ConvertLB.Factory factory) { + this.json = checkNotNull(json, "json"); + this.factory = checkNotNull(factory, "factory"); } @Override public LoadBalancer apply(HttpResponse arg0) { + checkState(convertLB != null, "convertLB should be set by InvocationContext"); Map map = json.apply(arg0); if (map == null || map.size() == 0) return null; @@ -59,7 +67,7 @@ public class UnwrapLoadBalancer implements Function, } UnwrapLoadBalancer setRegion(String region) { - this.convertLB = new ConvertLB(region); + this.convertLB = factory.createForRegion(region); return this; } diff --git a/apis/cloudloadbalancers/src/main/java/org/jclouds/cloudloadbalancers/functions/UnwrapLoadBalancers.java b/apis/cloudloadbalancers/src/main/java/org/jclouds/cloudloadbalancers/functions/UnwrapLoadBalancers.java index a5e8cb8437..39c83f7029 100644 --- a/apis/cloudloadbalancers/src/main/java/org/jclouds/cloudloadbalancers/functions/UnwrapLoadBalancers.java +++ b/apis/cloudloadbalancers/src/main/java/org/jclouds/cloudloadbalancers/functions/UnwrapLoadBalancers.java @@ -18,12 +18,15 @@ */ package org.jclouds.cloudloadbalancers.functions; +import static com.google.common.base.Preconditions.checkNotNull; + import java.util.Map; import java.util.Set; import javax.inject.Inject; import org.jclouds.cloudloadbalancers.domain.LoadBalancer; +import org.jclouds.cloudloadbalancers.functions.ConvertLB.Factory; import org.jclouds.http.HttpRequest; import org.jclouds.http.HttpResponse; import org.jclouds.http.functions.ParseJson; @@ -40,11 +43,14 @@ public class UnwrapLoadBalancers implements Function { private final ParseJson>> json; + private final Factory factory; + private ConvertLB convertLB; @Inject - UnwrapLoadBalancers(ParseJson>> json) { - this.json = json; + UnwrapLoadBalancers(ParseJson>> json, ConvertLB.Factory factory) { + this.json = checkNotNull(json, "json"); + this.factory = checkNotNull(factory, "factory"); } @Override @@ -62,7 +68,7 @@ public class UnwrapLoadBalancers implements Function { @Override @@ -67,6 +69,20 @@ public class UnwrapLoadBalancerTest extends BaseItemParserTest { new SimpleDateFormatDateService().iso8601SecondsDateParse("2010-11-30T03:23:44Z")).build(); } + // add factory binding as this is not default + @Override + protected Injector injector() { + return super.injector().createChildInjector(new AbstractModule() { + + @Override + protected void configure() { + install(new FactoryModuleBuilder().build(ConvertLB.Factory.class)); + } + + }); + + } + @Override protected Function parser(Injector i) { return i.getInstance(UnwrapLoadBalancer.class).setRegion("DFW"); diff --git a/apis/cloudloadbalancers/src/test/java/org/jclouds/cloudloadbalancers/functions/UnwrapLoadBalancerWhenDeletedTest.java b/apis/cloudloadbalancers/src/test/java/org/jclouds/cloudloadbalancers/functions/UnwrapLoadBalancerWhenDeletedTest.java new file mode 100644 index 0000000000..bd8501e40a --- /dev/null +++ b/apis/cloudloadbalancers/src/test/java/org/jclouds/cloudloadbalancers/functions/UnwrapLoadBalancerWhenDeletedTest.java @@ -0,0 +1,70 @@ +/** + * Licensed to jclouds, Inc. (jclouds) under one or more + * contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. jclouds licenses this file + * to you 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.cloudloadbalancers.functions; + +import org.jclouds.cloudloadbalancers.domain.LoadBalancer; +import org.jclouds.cloudloadbalancers.domain.LoadBalancer.Status; +import org.jclouds.date.internal.SimpleDateFormatDateService; +import org.jclouds.http.HttpResponse; +import org.jclouds.json.BaseItemParserTest; +import org.testng.annotations.Test; + +import com.google.common.base.Function; +import com.google.inject.AbstractModule; +import com.google.inject.Injector; +import com.google.inject.assistedinject.FactoryModuleBuilder; + +/** + * + * @author Adrian Cole + */ +@Test(groups = "unit", testName = "UnwrapLoadBalancerWhenDeletedTest") +public class UnwrapLoadBalancerWhenDeletedTest extends BaseItemParserTest { + + @Override + public String resource() { + return "/getloadbalancer-deleted.json"; + } + + @Override + public LoadBalancer expected() { + return LoadBalancer.builder().region("LON").id(4865).name("adriancole-LON").status(Status.DELETED).created( + new SimpleDateFormatDateService().iso8601SecondsDateParse("2011-12-05T18:03:23Z")).updated( + new SimpleDateFormatDateService().iso8601SecondsDateParse("2011-12-05T18:04:04Z")).build(); + } + + // add factory binding as this is not default + @Override + protected Injector injector() { + return super.injector().createChildInjector(new AbstractModule() { + + @Override + protected void configure() { + install(new FactoryModuleBuilder().build(ConvertLB.Factory.class)); + } + + }); + + } + + @Override + protected Function parser(Injector i) { + return i.getInstance(UnwrapLoadBalancer.class).setRegion("LON"); + } +} diff --git a/apis/cloudloadbalancers/src/test/java/org/jclouds/cloudloadbalancers/functions/UnwrapLoadBalancersTest.java b/apis/cloudloadbalancers/src/test/java/org/jclouds/cloudloadbalancers/functions/UnwrapLoadBalancersTest.java index c31b429e82..95b1e0d848 100644 --- a/apis/cloudloadbalancers/src/test/java/org/jclouds/cloudloadbalancers/functions/UnwrapLoadBalancersTest.java +++ b/apis/cloudloadbalancers/src/test/java/org/jclouds/cloudloadbalancers/functions/UnwrapLoadBalancersTest.java @@ -30,7 +30,9 @@ import org.testng.annotations.Test; import com.google.common.base.Function; import com.google.common.collect.ImmutableSet; +import com.google.inject.AbstractModule; import com.google.inject.Injector; +import com.google.inject.assistedinject.FactoryModuleBuilder; /** * @@ -64,6 +66,20 @@ public class UnwrapLoadBalancersTest extends BaseSetParserTest { } + // add factory binding as this is not default + @Override + protected Injector injector() { + return super.injector().createChildInjector(new AbstractModule() { + + @Override + protected void configure() { + install(new FactoryModuleBuilder().build(ConvertLB.Factory.class)); + } + + }); + + } + @Override protected Function> parser(Injector i) { return i.getInstance(UnwrapLoadBalancers.class).setRegion("DFW"); diff --git a/apis/cloudloadbalancers/src/test/resources/getloadbalancer-deleted.json b/apis/cloudloadbalancers/src/test/resources/getloadbalancer-deleted.json new file mode 100644 index 0000000000..d4bdf18562 --- /dev/null +++ b/apis/cloudloadbalancers/src/test/resources/getloadbalancer-deleted.json @@ -0,0 +1 @@ +{"loadBalancer":{"name":"adriancole-LON","id":4865,"status":"DELETED","created":{"time":"2011-12-05T18:03:23Z"},"updated":{"time":"2011-12-05T18:04:04Z"}}} \ No newline at end of file