algorithm can be null when lb is deleted

This commit is contained in:
Adrian Cole 2011-12-05 10:27:56 -08:00
parent 1680931776
commit 0068fbbd63
10 changed files with 204 additions and 54 deletions

View File

@ -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();
}

View File

@ -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<Node, LoadBalancer> {
this.status = status;
return this;
}
public Builder algorithm(Algorithm algorithm) {
algorithm(algorithm.name());
return this;
algorithm(algorithm.name());
return this;
}
public Builder virtualIPs(Iterable<VirtualIP> virtualIPs) {
@ -212,51 +213,50 @@ public class LoadBalancer extends BaseLoadBalancer<Node, LoadBalancer> {
}
}
/**
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<Node, LoadBalancer> {
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<VirtualIP> virtualIPs, Iterable<Node> 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<VirtualIP> virtualIPs, Iterable<Node> 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<Node, LoadBalancer> {
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<VirtualIP> getVirtualIPs() {

View File

@ -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<N extends BaseNode<N>, T extends BaseLoadBalancer<
// so tests will come out consistently
protected SortedSet<N> nodes = ImmutableSortedSet.of();
public BaseLoadBalancer(String name, String protocol, Integer port, String algorithm, Iterable<N> nodes) {
public BaseLoadBalancer(String name, String protocol, Integer port, @Nullable String algorithm, Iterable<N> 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<N extends BaseNode<N>, T extends BaseLoadBalancer<
return port;
}
/**
*
* @return algorithm, which may be null if the load balancer is deleted
*/
@Nullable
public String getAlgorithm() {
return algorithm;
}

View File

@ -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<LB, LoadBalancer> {
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;
}
}
}

View File

@ -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<HttpResponse, LoadBalancer>, InvocationContext<UnwrapLoadBalancer> {
private final ParseJson<Map<String, LB>> json;
private final Factory factory;
private ConvertLB convertLB;
@Inject
UnwrapLoadBalancer(ParseJson<Map<String, LB>> json) {
this.json = json;
UnwrapLoadBalancer(ParseJson<Map<String, LB>> 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<String, LB> map = json.apply(arg0);
if (map == null || map.size() == 0)
return null;
@ -59,7 +67,7 @@ public class UnwrapLoadBalancer implements Function<HttpResponse, LoadBalancer>,
}
UnwrapLoadBalancer setRegion(String region) {
this.convertLB = new ConvertLB(region);
this.convertLB = factory.createForRegion(region);
return this;
}

View File

@ -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<HttpResponse, Set<LoadBalan
InvocationContext<UnwrapLoadBalancers> {
private final ParseJson<Map<String, Set<LB>>> json;
private final Factory factory;
private ConvertLB convertLB;
@Inject
UnwrapLoadBalancers(ParseJson<Map<String, Set<LB>>> json) {
this.json = json;
UnwrapLoadBalancers(ParseJson<Map<String, Set<LB>>> json, ConvertLB.Factory factory) {
this.json = checkNotNull(json, "json");
this.factory = checkNotNull(factory, "factory");
}
@Override
@ -62,7 +68,7 @@ public class UnwrapLoadBalancers implements Function<HttpResponse, Set<LoadBalan
}
UnwrapLoadBalancers setRegion(String region) {
this.convertLB = new ConvertLB(region);
this.convertLB = factory.createForRegion(region);
return this;
}

View File

@ -30,13 +30,15 @@ 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;
/**
*
* @author Adrian Cole
*/
@Test(groups = "unit")
@Test(groups = "unit", testName = "UnwrapLoadBalancerTest")
public class UnwrapLoadBalancerTest extends BaseItemParserTest<LoadBalancer> {
@Override
@ -67,6 +69,20 @@ public class UnwrapLoadBalancerTest extends BaseItemParserTest<LoadBalancer> {
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<HttpResponse, LoadBalancer> parser(Injector i) {
return i.getInstance(UnwrapLoadBalancer.class).setRegion("DFW");

View File

@ -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<LoadBalancer> {
@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<HttpResponse, LoadBalancer> parser(Injector i) {
return i.getInstance(UnwrapLoadBalancer.class).setRegion("LON");
}
}

View File

@ -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<LoadBalancer> {
}
// 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<HttpResponse, Set<LoadBalancer>> parser(Injector i) {
return i.getInstance(UnwrapLoadBalancers.class).setRegion("DFW");

View File

@ -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"}}}