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.LoadBalancerClient;
import org.jclouds.cloudloadbalancers.features.NodeAsyncClient; import org.jclouds.cloudloadbalancers.features.NodeAsyncClient;
import org.jclouds.cloudloadbalancers.features.NodeClient; import org.jclouds.cloudloadbalancers.features.NodeClient;
import org.jclouds.cloudloadbalancers.functions.ConvertLB;
import org.jclouds.cloudloadbalancers.handlers.ParseCloudLoadBalancersErrorFromHttpResponse; import org.jclouds.cloudloadbalancers.handlers.ParseCloudLoadBalancersErrorFromHttpResponse;
import org.jclouds.cloudloadbalancers.reference.RackspaceConstants; import org.jclouds.cloudloadbalancers.reference.RackspaceConstants;
import org.jclouds.http.HttpErrorHandler; import org.jclouds.http.HttpErrorHandler;
@ -63,6 +64,7 @@ import com.google.inject.Injector;
import com.google.inject.Provides; import com.google.inject.Provides;
import com.google.inject.Scopes; import com.google.inject.Scopes;
import com.google.inject.TypeLiteral; import com.google.inject.TypeLiteral;
import com.google.inject.assistedinject.FactoryModuleBuilder;
/** /**
* Configures theRackspace Cloud Load Balancers connection. * Configures theRackspace Cloud Load Balancers connection.
@ -109,6 +111,7 @@ public class CloudLoadBalancersRestClientModule extends
install(new OpenStackAuthenticationModule()); install(new OpenStackAuthenticationModule());
bind(DateAdapter.class).to(Iso8601DateAdapter.class); bind(DateAdapter.class).to(Iso8601DateAdapter.class);
bindRegionsToProvider(); bindRegionsToProvider();
install(new FactoryModuleBuilder().build(ConvertLB.Factory.class));
super.configure(); super.configure();
} }

View File

@ -25,6 +25,7 @@ import java.util.Date;
import java.util.Set; import java.util.Set;
import org.jclouds.cloudloadbalancers.domain.internal.BaseLoadBalancer; import org.jclouds.cloudloadbalancers.domain.internal.BaseLoadBalancer;
import org.jclouds.javax.annotation.Nullable;
import com.google.common.collect.ImmutableSet; import com.google.common.collect.ImmutableSet;
@ -214,12 +215,12 @@ public class LoadBalancer extends BaseLoadBalancer<Node, LoadBalancer> {
} }
/** /**
All load balancers utilize an algorithm that defines how traffic should be directed between * 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 * back-end nodes. The default algorithm for newly created load balancers is RANDOM, which can be
be overridden at creation time or changed after the load balancer has been initially * overridden at creation time or changed after the load balancer has been initially provisioned.
provisioned. The algorithm name is to be constant within a major revision of the load * The algorithm name is to be constant within a major revision of the load balancing API, though
balancing API, though new algorithms may be created with a unique algorithm name within * new algorithms may be created with a unique algorithm name within a given major revision of
a given major revision of the service API. * the service API.
*/ */
public static enum Algorithm { public static enum Algorithm {
/** /**
@ -235,28 +236,27 @@ public class LoadBalancer extends BaseLoadBalancer<Node, LoadBalancer> {
*/ */
ROUND_ROBIN, ROUND_ROBIN,
/** /**
* Each request will be assigned to a node based on the number of concurrent connections * Each request will be assigned to a node based on the number of concurrent connections to
* to the node and its weight. * the node and its weight.
*/ */
WEIGHTED_LEAST_CONNECTIONS, WEIGHTED_LEAST_CONNECTIONS,
/** /**
* A round robin algorithm, but with different proportions of traffic being directed to * A round robin algorithm, but with different proportions of traffic being directed to the
* the back-end nodes. Weights must be defined as part of the load balancer's node configuration. * back-end nodes. Weights must be defined as part of the load balancer's node configuration.
*/ */
WEIGHTED_ROUND_ROBIN, WEIGHTED_ROUND_ROBIN, UNRECOGNIZED;
UNRECOGNIZED;
public static Algorithm fromValue(String status) { public static Algorithm fromValue(String algorithm) {
try { try {
return valueOf(checkNotNull(status, "status")); return valueOf(checkNotNull(algorithm, "algorithm"));
} catch (IllegalArgumentException e) { } catch (IllegalArgumentException e) {
return UNRECOGNIZED; return UNRECOGNIZED;
} }
} }
} }
public static Algorithm[] WEIGHTED_ALGORITHMS = {Algorithm.WEIGHTED_LEAST_CONNECTIONS, public static Algorithm[] WEIGHTED_ALGORITHMS = { Algorithm.WEIGHTED_LEAST_CONNECTIONS,
Algorithm.WEIGHTED_ROUND_ROBIN}; Algorithm.WEIGHTED_ROUND_ROBIN };
private final String region; private final String region;
private final int id; private final int id;
@ -269,15 +269,15 @@ public class LoadBalancer extends BaseLoadBalancer<Node, LoadBalancer> {
private final Date updated; private final Date updated;
private final boolean connectionLoggingEnabled; private final boolean connectionLoggingEnabled;
public LoadBalancer(String region, int id, String name, String protocol, Integer port, String algorithm, Status status, public LoadBalancer(String region, int id, String name, String protocol, Integer port, @Nullable String algorithm,
Iterable<VirtualIP> virtualIPs, Iterable<Node> nodes, String sessionPersistenceType, String clusterName, Status status, Iterable<VirtualIP> virtualIPs, Iterable<Node> nodes, String sessionPersistenceType,
Date created, Date updated, boolean connectionLoggingEnabled) { String clusterName, Date created, Date updated, boolean connectionLoggingEnabled) {
super(name, protocol, port, algorithm, nodes); super(name, protocol, port, algorithm, nodes);
this.region = checkNotNull(region, "region"); this.region = checkNotNull(region, "region");
checkArgument(id != -1, "id must be specified"); checkArgument(id != -1, "id must be specified");
this.id = id; this.id = id;
this.status = checkNotNull(status, "status"); 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.virtualIPs = ImmutableSet.copyOf(checkNotNull(virtualIPs, "virtualIPs"));
this.sessionPersistenceType = sessionPersistenceType; this.sessionPersistenceType = sessionPersistenceType;
this.clusterName = clusterName; this.clusterName = clusterName;
@ -298,6 +298,11 @@ public class LoadBalancer extends BaseLoadBalancer<Node, LoadBalancer> {
return status; return status;
} }
/**
*
* @return algorithm, which may be null if the load balancer is deleted
*/
@Nullable
public Algorithm getTypedAlgorithm() { public Algorithm getTypedAlgorithm() {
return algorithm; return algorithm;
} }

View File

@ -23,6 +23,8 @@ import static com.google.common.base.Preconditions.checkNotNull;
import java.util.Set; import java.util.Set;
import java.util.SortedSet; import java.util.SortedSet;
import org.jclouds.javax.annotation.Nullable;
import com.google.common.collect.ImmutableSet; import com.google.common.collect.ImmutableSet;
import com.google.common.collect.ImmutableSortedSet; import com.google.common.collect.ImmutableSortedSet;
import com.google.common.collect.Sets; 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 // so tests will come out consistently
protected SortedSet<N> nodes = ImmutableSortedSet.of(); 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.name = checkNotNull(name, "name");
this.protocol = protocol;// null on deleted LB this.protocol = protocol;// null on deleted LB
this.port = port;// 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 port;
} }
/**
*
* @return algorithm, which may be null if the load balancer is deleted
*/
@Nullable
public String getAlgorithm() { public String getAlgorithm() {
return algorithm; return algorithm;
} }

View File

@ -18,25 +18,39 @@
*/ */
package org.jclouds.cloudloadbalancers.functions; 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;
import org.jclouds.cloudloadbalancers.domain.LoadBalancer.Builder; import org.jclouds.cloudloadbalancers.domain.LoadBalancer.Builder;
import org.jclouds.logging.Logger;
import com.google.common.base.Function; import com.google.common.base.Function;
import com.google.common.collect.Iterables; import com.google.common.collect.Iterables;
import com.google.inject.assistedinject.Assisted;
/** /**
* @author Adrian Cole * @author Adrian Cole
*/ */
public class ConvertLB implements Function<LB, LoadBalancer> { 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; private final String region;
ConvertLB(String region) { @Inject
ConvertLB(@Assisted String region) {
this.region = region.toUpperCase(); this.region = region.toUpperCase();
} }
@Override @Override
public LoadBalancer apply(LB lb) { public LoadBalancer apply(LB lb) {
try {
Builder builder = LoadBalancer.builder().region(region).name(lb.getName()).port(lb.getPort()).protocol( 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) lb.getProtocol()).algorithm(lb.getAlgorithm()).nodes(lb.getNodes()).id(lb.id).status(lb.status)
.virtualIPs(lb.virtualIps); .virtualIPs(lb.virtualIps);
@ -51,6 +65,10 @@ public class ConvertLB implements Function<LB, LoadBalancer> {
if (lb.connectionLogging.size() == 1) if (lb.connectionLogging.size() == 1)
builder.connectionLoggingEnabled(Iterables.get(lb.connectionLogging.values(), 0)); builder.connectionLoggingEnabled(Iterables.get(lb.connectionLogging.values(), 0));
return builder.build(); 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; 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 java.util.Map;
import javax.inject.Inject; import javax.inject.Inject;
import org.jclouds.cloudloadbalancers.domain.LoadBalancer; import org.jclouds.cloudloadbalancers.domain.LoadBalancer;
import org.jclouds.cloudloadbalancers.functions.ConvertLB.Factory;
import org.jclouds.http.HttpRequest; import org.jclouds.http.HttpRequest;
import org.jclouds.http.HttpResponse; import org.jclouds.http.HttpResponse;
import org.jclouds.http.functions.ParseJson; 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> { public class UnwrapLoadBalancer implements Function<HttpResponse, LoadBalancer>, InvocationContext<UnwrapLoadBalancer> {
private final ParseJson<Map<String, LB>> json; private final ParseJson<Map<String, LB>> json;
private final Factory factory;
private ConvertLB convertLB; private ConvertLB convertLB;
@Inject @Inject
UnwrapLoadBalancer(ParseJson<Map<String, LB>> json) { UnwrapLoadBalancer(ParseJson<Map<String, LB>> json, ConvertLB.Factory factory) {
this.json = json; this.json = checkNotNull(json, "json");
this.factory = checkNotNull(factory, "factory");
} }
@Override @Override
public LoadBalancer apply(HttpResponse arg0) { public LoadBalancer apply(HttpResponse arg0) {
checkState(convertLB != null, "convertLB should be set by InvocationContext");
Map<String, LB> map = json.apply(arg0); Map<String, LB> map = json.apply(arg0);
if (map == null || map.size() == 0) if (map == null || map.size() == 0)
return null; return null;
@ -59,7 +67,7 @@ public class UnwrapLoadBalancer implements Function<HttpResponse, LoadBalancer>,
} }
UnwrapLoadBalancer setRegion(String region) { UnwrapLoadBalancer setRegion(String region) {
this.convertLB = new ConvertLB(region); this.convertLB = factory.createForRegion(region);
return this; return this;
} }

View File

@ -18,12 +18,15 @@
*/ */
package org.jclouds.cloudloadbalancers.functions; package org.jclouds.cloudloadbalancers.functions;
import static com.google.common.base.Preconditions.checkNotNull;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
import javax.inject.Inject; import javax.inject.Inject;
import org.jclouds.cloudloadbalancers.domain.LoadBalancer; import org.jclouds.cloudloadbalancers.domain.LoadBalancer;
import org.jclouds.cloudloadbalancers.functions.ConvertLB.Factory;
import org.jclouds.http.HttpRequest; import org.jclouds.http.HttpRequest;
import org.jclouds.http.HttpResponse; import org.jclouds.http.HttpResponse;
import org.jclouds.http.functions.ParseJson; import org.jclouds.http.functions.ParseJson;
@ -40,11 +43,14 @@ public class UnwrapLoadBalancers implements Function<HttpResponse, Set<LoadBalan
InvocationContext<UnwrapLoadBalancers> { InvocationContext<UnwrapLoadBalancers> {
private final ParseJson<Map<String, Set<LB>>> json; private final ParseJson<Map<String, Set<LB>>> json;
private final Factory factory;
private ConvertLB convertLB; private ConvertLB convertLB;
@Inject @Inject
UnwrapLoadBalancers(ParseJson<Map<String, Set<LB>>> json) { UnwrapLoadBalancers(ParseJson<Map<String, Set<LB>>> json, ConvertLB.Factory factory) {
this.json = json; this.json = checkNotNull(json, "json");
this.factory = checkNotNull(factory, "factory");
} }
@Override @Override
@ -62,7 +68,7 @@ public class UnwrapLoadBalancers implements Function<HttpResponse, Set<LoadBalan
} }
UnwrapLoadBalancers setRegion(String region) { UnwrapLoadBalancers setRegion(String region) {
this.convertLB = new ConvertLB(region); this.convertLB = factory.createForRegion(region);
return this; return this;
} }

View File

@ -30,13 +30,15 @@ import org.testng.annotations.Test;
import com.google.common.base.Function; import com.google.common.base.Function;
import com.google.common.collect.ImmutableSet; import com.google.common.collect.ImmutableSet;
import com.google.inject.AbstractModule;
import com.google.inject.Injector; import com.google.inject.Injector;
import com.google.inject.assistedinject.FactoryModuleBuilder;
/** /**
* *
* @author Adrian Cole * @author Adrian Cole
*/ */
@Test(groups = "unit") @Test(groups = "unit", testName = "UnwrapLoadBalancerTest")
public class UnwrapLoadBalancerTest extends BaseItemParserTest<LoadBalancer> { public class UnwrapLoadBalancerTest extends BaseItemParserTest<LoadBalancer> {
@Override @Override
@ -67,6 +69,20 @@ public class UnwrapLoadBalancerTest extends BaseItemParserTest<LoadBalancer> {
new SimpleDateFormatDateService().iso8601SecondsDateParse("2010-11-30T03:23:44Z")).build(); 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 @Override
protected Function<HttpResponse, LoadBalancer> parser(Injector i) { protected Function<HttpResponse, LoadBalancer> parser(Injector i) {
return i.getInstance(UnwrapLoadBalancer.class).setRegion("DFW"); 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.base.Function;
import com.google.common.collect.ImmutableSet; import com.google.common.collect.ImmutableSet;
import com.google.inject.AbstractModule;
import com.google.inject.Injector; 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 @Override
protected Function<HttpResponse, Set<LoadBalancer>> parser(Injector i) { protected Function<HttpResponse, Set<LoadBalancer>> parser(Injector i) {
return i.getInstance(UnwrapLoadBalancers.class).setRegion("DFW"); 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"}}}