From 47c38b55f97a43a357a32022b2789ab82108652e Mon Sep 17 00:00:00 2001 From: Everett Toews Date: Thu, 17 Jan 2013 10:47:27 -0600 Subject: [PATCH] The Virtual IP API for Rackspace Cloud Load Balancers. --- .../CloudLoadBalancersApi.java | 9 ++ .../CloudLoadBalancersAsyncApi.java | 13 +- .../CloudLoadBalancersRestClientModule.java | 3 + .../domain/LoadBalancer.java | 12 +- .../cloudloadbalancers/domain/VirtualIP.java | 81 +++--------- .../domain/VirtualIPWithId.java | 73 +++++++++++ .../features/VirtualIPApi.java | 65 ++++++++++ .../features/VirtualIPAsyncApi.java | 90 +++++++++++++ .../functions/ConvertLB.java | 7 +- .../cloudloadbalancers/functions/LB.java | 6 +- .../LoadBalancerToLoadBalancerMetadata.java | 6 +- .../features/VirtualIPApiExpectTest.java | 99 ++++++++++++++ .../features/VirtualIPApiLiveTest.java | 121 ++++++++++++++++++ .../functions/ParseLoadBalancerTest.java | 6 +- .../functions/ParseLoadBalancersTest.java | 7 +- .../resources/virtualips-create-response.json | 6 + .../src/test/resources/virtualips-create.json | 1 + .../src/test/resources/virtualips-list.json | 22 ++++ 18 files changed, 539 insertions(+), 88 deletions(-) create mode 100644 apis/rackspace-cloudloadbalancers/src/main/java/org/jclouds/rackspace/cloudloadbalancers/domain/VirtualIPWithId.java create mode 100644 apis/rackspace-cloudloadbalancers/src/main/java/org/jclouds/rackspace/cloudloadbalancers/features/VirtualIPApi.java create mode 100644 apis/rackspace-cloudloadbalancers/src/main/java/org/jclouds/rackspace/cloudloadbalancers/features/VirtualIPAsyncApi.java create mode 100644 apis/rackspace-cloudloadbalancers/src/test/java/org/jclouds/rackspace/cloudloadbalancers/features/VirtualIPApiExpectTest.java create mode 100644 apis/rackspace-cloudloadbalancers/src/test/java/org/jclouds/rackspace/cloudloadbalancers/features/VirtualIPApiLiveTest.java create mode 100644 apis/rackspace-cloudloadbalancers/src/test/resources/virtualips-create-response.json create mode 100644 apis/rackspace-cloudloadbalancers/src/test/resources/virtualips-create.json create mode 100644 apis/rackspace-cloudloadbalancers/src/test/resources/virtualips-list.json diff --git a/apis/rackspace-cloudloadbalancers/src/main/java/org/jclouds/rackspace/cloudloadbalancers/CloudLoadBalancersApi.java b/apis/rackspace-cloudloadbalancers/src/main/java/org/jclouds/rackspace/cloudloadbalancers/CloudLoadBalancersApi.java index 55d77ec427..b3c34aebc2 100644 --- a/apis/rackspace-cloudloadbalancers/src/main/java/org/jclouds/rackspace/cloudloadbalancers/CloudLoadBalancersApi.java +++ b/apis/rackspace-cloudloadbalancers/src/main/java/org/jclouds/rackspace/cloudloadbalancers/CloudLoadBalancersApi.java @@ -28,6 +28,7 @@ import org.jclouds.location.functions.ZoneToEndpoint; import org.jclouds.rackspace.cloudloadbalancers.features.AccessRuleApi; import org.jclouds.rackspace.cloudloadbalancers.features.LoadBalancerApi; import org.jclouds.rackspace.cloudloadbalancers.features.NodeApi; +import org.jclouds.rackspace.cloudloadbalancers.features.VirtualIPApi; import org.jclouds.rest.annotations.Delegate; import org.jclouds.rest.annotations.EndpointParam; @@ -70,4 +71,12 @@ public interface CloudLoadBalancersApi { @Path("/loadbalancers/{lbId}") AccessRuleApi getAccessRuleApiForZoneAndLoadBalancer( @EndpointParam(parser = ZoneToEndpoint.class) @Nullable String zone, @PathParam("lbId") int lbId); + + /** + * Provides synchronous access to Virtual IP features. + */ + @Delegate + @Path("/loadbalancers/{lbId}") + VirtualIPApi getVirtualIPApiForZoneAndLoadBalancer( + @EndpointParam(parser = ZoneToEndpoint.class) @Nullable String zone, @PathParam("lbId") int lbId); } diff --git a/apis/rackspace-cloudloadbalancers/src/main/java/org/jclouds/rackspace/cloudloadbalancers/CloudLoadBalancersAsyncApi.java b/apis/rackspace-cloudloadbalancers/src/main/java/org/jclouds/rackspace/cloudloadbalancers/CloudLoadBalancersAsyncApi.java index f69a850f61..96119b0ce3 100644 --- a/apis/rackspace-cloudloadbalancers/src/main/java/org/jclouds/rackspace/cloudloadbalancers/CloudLoadBalancersAsyncApi.java +++ b/apis/rackspace-cloudloadbalancers/src/main/java/org/jclouds/rackspace/cloudloadbalancers/CloudLoadBalancersAsyncApi.java @@ -26,9 +26,10 @@ import javax.ws.rs.PathParam; import org.jclouds.javax.annotation.Nullable; import org.jclouds.location.Zone; import org.jclouds.location.functions.ZoneToEndpoint; -import org.jclouds.rackspace.cloudloadbalancers.features.AccessRuleApi; +import org.jclouds.rackspace.cloudloadbalancers.features.AccessRuleAsyncApi; import org.jclouds.rackspace.cloudloadbalancers.features.LoadBalancerAsyncApi; import org.jclouds.rackspace.cloudloadbalancers.features.NodeAsyncApi; +import org.jclouds.rackspace.cloudloadbalancers.features.VirtualIPAsyncApi; import org.jclouds.rest.annotations.Delegate; import org.jclouds.rest.annotations.EndpointParam; @@ -69,6 +70,14 @@ public interface CloudLoadBalancersAsyncApi { */ @Delegate @Path("/loadbalancers/{lbId}") - AccessRuleApi getAccessRuleApiForZoneAndLoadBalancer( + AccessRuleAsyncApi getAccessRuleApiForZoneAndLoadBalancer( + @EndpointParam(parser = ZoneToEndpoint.class) @Nullable String zone, @PathParam("lbId") int lbId); + + /** + * Provides synchronous access to Virtual IP features. + */ + @Delegate + @Path("/loadbalancers/{lbId}") + VirtualIPAsyncApi getVirtualIPApiForZoneAndLoadBalancer( @EndpointParam(parser = ZoneToEndpoint.class) @Nullable String zone, @PathParam("lbId") int lbId); } diff --git a/apis/rackspace-cloudloadbalancers/src/main/java/org/jclouds/rackspace/cloudloadbalancers/config/CloudLoadBalancersRestClientModule.java b/apis/rackspace-cloudloadbalancers/src/main/java/org/jclouds/rackspace/cloudloadbalancers/config/CloudLoadBalancersRestClientModule.java index 8ebace2dfb..7b7c2d6212 100644 --- a/apis/rackspace-cloudloadbalancers/src/main/java/org/jclouds/rackspace/cloudloadbalancers/config/CloudLoadBalancersRestClientModule.java +++ b/apis/rackspace-cloudloadbalancers/src/main/java/org/jclouds/rackspace/cloudloadbalancers/config/CloudLoadBalancersRestClientModule.java @@ -34,6 +34,8 @@ import org.jclouds.rackspace.cloudloadbalancers.features.LoadBalancerAsyncApi; import org.jclouds.rackspace.cloudloadbalancers.features.LoadBalancerApi; import org.jclouds.rackspace.cloudloadbalancers.features.NodeAsyncApi; import org.jclouds.rackspace.cloudloadbalancers.features.NodeApi; +import org.jclouds.rackspace.cloudloadbalancers.features.VirtualIPApi; +import org.jclouds.rackspace.cloudloadbalancers.features.VirtualIPAsyncApi; import org.jclouds.rackspace.cloudloadbalancers.functions.ConvertLB; import org.jclouds.rackspace.cloudloadbalancers.handlers.ParseCloudLoadBalancersErrorFromHttpResponse; import org.jclouds.rest.ConfiguresRestClient; @@ -55,6 +57,7 @@ public class CloudLoadBalancersRestClientModule extends .put(LoadBalancerApi.class, LoadBalancerAsyncApi.class) .put(NodeApi.class, NodeAsyncApi.class) .put(AccessRuleApi.class, AccessRuleAsyncApi.class) + .put(VirtualIPApi.class, VirtualIPAsyncApi.class) .build(); public CloudLoadBalancersRestClientModule() { diff --git a/apis/rackspace-cloudloadbalancers/src/main/java/org/jclouds/rackspace/cloudloadbalancers/domain/LoadBalancer.java b/apis/rackspace-cloudloadbalancers/src/main/java/org/jclouds/rackspace/cloudloadbalancers/domain/LoadBalancer.java index be50dd50a8..1c6536693b 100644 --- a/apis/rackspace-cloudloadbalancers/src/main/java/org/jclouds/rackspace/cloudloadbalancers/domain/LoadBalancer.java +++ b/apis/rackspace-cloudloadbalancers/src/main/java/org/jclouds/rackspace/cloudloadbalancers/domain/LoadBalancer.java @@ -41,7 +41,7 @@ public class LoadBalancer extends BaseLoadBalancer { private final String region; private final int id; private final Status status; - private final Set virtualIPs; + private final Set virtualIPs; private final String clusterName; private final Date created; private final Date updated; @@ -53,7 +53,7 @@ public class LoadBalancer extends BaseLoadBalancer { public LoadBalancer(String region, int id, String name, String protocol, @Nullable Integer port, Set nodes, @Nullable Integer timeout, @Nullable Boolean halfClosed, @Nullable Algorithm algorithm, Status status, - Set virtualIPs, @Nullable Map sessionPersistenceType, + Set virtualIPs, @Nullable Map sessionPersistenceType, String clusterName, Date created, Date updated, @Nullable Map connectionLogging, @Nullable ConnectionThrottle connectionThrottle, boolean contentCaching, int nodeCount, @Nullable HealthMonitor healthMonitor, @Nullable SSLTermination sslTermination, @@ -94,7 +94,7 @@ public class LoadBalancer extends BaseLoadBalancer { /** * @see VirtualIP */ - public Set getVirtualIPs() { + public Set getVirtualIPs() { return virtualIPs; } @@ -251,7 +251,7 @@ public class LoadBalancer extends BaseLoadBalancer { private String region; private int id = -1; private Status status; - private Set virtualIPs = ImmutableSet. of(); + private Set virtualIPs = ImmutableSet. of(); private String clusterName; private Date created; private Date updated; @@ -276,8 +276,8 @@ public class LoadBalancer extends BaseLoadBalancer { return this; } - public Builder virtualIPs(Iterable virtualIPs) { - this.virtualIPs = ImmutableSet. copyOf(checkNotNull(virtualIPs, "virtualIPs")); + public Builder virtualIPs(Iterable virtualIPs) { + this.virtualIPs = ImmutableSet. copyOf(checkNotNull(virtualIPs, "virtualIPs")); return this; } diff --git a/apis/rackspace-cloudloadbalancers/src/main/java/org/jclouds/rackspace/cloudloadbalancers/domain/VirtualIP.java b/apis/rackspace-cloudloadbalancers/src/main/java/org/jclouds/rackspace/cloudloadbalancers/domain/VirtualIP.java index 7357417a80..bc01cb3302 100644 --- a/apis/rackspace-cloudloadbalancers/src/main/java/org/jclouds/rackspace/cloudloadbalancers/domain/VirtualIP.java +++ b/apis/rackspace-cloudloadbalancers/src/main/java/org/jclouds/rackspace/cloudloadbalancers/domain/VirtualIP.java @@ -18,7 +18,6 @@ */ package org.jclouds.rackspace.cloudloadbalancers.domain; -import static com.google.common.base.Preconditions.checkArgument; import static com.google.common.base.Preconditions.checkNotNull; import com.google.common.base.Objects; @@ -26,38 +25,28 @@ import com.google.common.base.Objects.ToStringHelper; /** * A virtual IP (VIP) makes a load balancer accessible by clients. The load balancing service - * supports either a public VIP, routable on the public Internet, or a ServiceNet address, routable + * supports either a public virtual IP, routable on the public Internet, or a ServiceNet address, routable * only within the region in which the load balancer resides. * - * @author Adrian Cole + * @author Everett Toews */ -public class VirtualIP implements Comparable { +public class VirtualIP { - private int id; - private String address; private Type type; private IPVersion ipVersion; - // for serialization only - VirtualIP() { + /** + * Use this method to easily create virtual IPs. Only public IPv6 virtual IPs can be created. + */ + public static VirtualIP publicIPv6() { + return new VirtualIP(Type.PUBLIC, IPVersion.IPV6); } - - public VirtualIP(int id, String address, Type type, IPVersion ipVersion) { - checkArgument(id != -1, "id must be specified"); - this.id = id; - this.address = checkNotNull(address, "address"); + + protected VirtualIP(Type type, IPVersion ipVersion) { this.type = checkNotNull(type, "type"); this.ipVersion = checkNotNull(ipVersion, "ipVersion"); } - public int getId() { - return id; - } - - public String getAddress() { - return address; - } - public Type getType() { return type; } @@ -66,14 +55,9 @@ public class VirtualIP implements Comparable { return ipVersion; } - @Override - public int compareTo(VirtualIP arg0) { - return address.compareTo(arg0.address); - } - protected ToStringHelper string() { return Objects.toStringHelper(this).omitNullValues() - .add("id", id).add("address", address).add("ipVersion", ipVersion).add("type", type); + .add("ipVersion", ipVersion).add("type", type); } @Override @@ -83,7 +67,7 @@ public class VirtualIP implements Comparable { @Override public int hashCode() { - return Objects.hashCode(id); + return Objects.hashCode(ipVersion, type); } @Override @@ -92,7 +76,8 @@ public class VirtualIP implements Comparable { if (obj == null || getClass() != obj.getClass()) return false; VirtualIP that = VirtualIP.class.cast(obj); - return Objects.equal(this.id, that.id); + return Objects.equal(this.ipVersion, that.ipVersion) + && Objects.equal(this.type, that.type); } /** @@ -104,7 +89,7 @@ public class VirtualIP implements Comparable { */ PUBLIC, /** - * An address that is routable only on ServiceNet. + * An address that is routable only on the Rackspace ServiceNet. */ SERVICENET, UNRECOGNIZED; @@ -132,41 +117,5 @@ public class VirtualIP implements Comparable { return UNRECOGNIZED; } } - - } - - public static class Builder { - private int id = -1; - private String address; - private Type type; - private IPVersion ipVersion = IPVersion.IPV4; - - public Builder id(int id) { - this.id = id; - return this; - } - - public Builder address(String address) { - this.address = address; - return this; - } - - public Builder type(Type type) { - this.type = type; - return this; - } - - public Builder ipVersion(IPVersion ipVersion) { - this.ipVersion = ipVersion; - return this; - } - - public VirtualIP build() { - return new VirtualIP(id, address, type, ipVersion); - } - } - - public static Builder builder() { - return new Builder(); } } diff --git a/apis/rackspace-cloudloadbalancers/src/main/java/org/jclouds/rackspace/cloudloadbalancers/domain/VirtualIPWithId.java b/apis/rackspace-cloudloadbalancers/src/main/java/org/jclouds/rackspace/cloudloadbalancers/domain/VirtualIPWithId.java new file mode 100644 index 0000000000..6b11ad1cbd --- /dev/null +++ b/apis/rackspace-cloudloadbalancers/src/main/java/org/jclouds/rackspace/cloudloadbalancers/domain/VirtualIPWithId.java @@ -0,0 +1,73 @@ +/** + * 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.rackspace.cloudloadbalancers.domain; + +import static com.google.common.base.Preconditions.checkNotNull; + +import com.google.common.base.Objects; +import com.google.common.base.Objects.ToStringHelper; + +/** + * @see VirtualIP + * + * @author Everett Toews + */ +public class VirtualIPWithId extends VirtualIP { + + private int id; + private String address; + + public VirtualIPWithId(Type type, IPVersion ipVersion, int id, String address) { + super(type, ipVersion); + this.id = id; + this.address = checkNotNull(address, "address"); + } + + public int getId() { + return id; + } + + public String getAddress() { + return address; + } + + protected ToStringHelper string() { + return Objects.toStringHelper(this).omitNullValues() + .add("id", id).add("address", address).add("ipVersion", getIpVersion()).add("type", getType()); + } + + @Override + public String toString() { + return string().toString(); + } + + @Override + public int hashCode() { + return Objects.hashCode(id); + } + + @Override + public boolean equals(Object obj) { + if (this == obj) return true; + if (obj == null || getClass() != obj.getClass()) return false; + + VirtualIPWithId that = VirtualIPWithId.class.cast(obj); + return Objects.equal(this.id, that.id); + } +} diff --git a/apis/rackspace-cloudloadbalancers/src/main/java/org/jclouds/rackspace/cloudloadbalancers/features/VirtualIPApi.java b/apis/rackspace-cloudloadbalancers/src/main/java/org/jclouds/rackspace/cloudloadbalancers/features/VirtualIPApi.java new file mode 100644 index 0000000000..d9bb4e37c7 --- /dev/null +++ b/apis/rackspace-cloudloadbalancers/src/main/java/org/jclouds/rackspace/cloudloadbalancers/features/VirtualIPApi.java @@ -0,0 +1,65 @@ +/** + * 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.rackspace.cloudloadbalancers.features; + +import org.jclouds.rackspace.cloudloadbalancers.domain.VirtualIP; +import org.jclouds.rackspace.cloudloadbalancers.domain.VirtualIPWithId; + +/** + * A virtual IP makes a load balancer accessible by clients. The load balancing service supports either a public VIP, + * routable on the public Internet, or a ServiceNet address, routable only within the region in which the load balancer + * resides. + *

+ * + * @see VirtualIPAsyncApi + * @author Everett Toews + */ +public interface VirtualIPApi { + /** + * Create a new virtual IP. + */ + VirtualIPWithId create(VirtualIP virtualIP); + + /** + * List the virtual IPs. + */ + Iterable list(); + + /** + * Remove a virtual IP. + * + * @see VirtualIPApi#remove(Iterable) + * + * @return true on a successful removal, false if the virtual IP was not found + */ + boolean remove(int id); + + /** + * Batch delete virtual IPs given the specified ids. + * + * All load balancers must have at least one virtual IP associated with them at all times. Attempting to delete the + * last virtual IP will result in an exception. The current default limit is ten ids per request. Any + * and all configuration data is immediately purged and is not recoverable. If one or more of the items in the list + * cannot be removed due to its current status, an exception is thrown along with the ids of the ones the + * system identified as potential failures for this request. + * + * @return true on a successful removal, false if the virtual IP was not found + */ + boolean remove(Iterable ids); +} \ No newline at end of file diff --git a/apis/rackspace-cloudloadbalancers/src/main/java/org/jclouds/rackspace/cloudloadbalancers/features/VirtualIPAsyncApi.java b/apis/rackspace-cloudloadbalancers/src/main/java/org/jclouds/rackspace/cloudloadbalancers/features/VirtualIPAsyncApi.java new file mode 100644 index 0000000000..43ec29222c --- /dev/null +++ b/apis/rackspace-cloudloadbalancers/src/main/java/org/jclouds/rackspace/cloudloadbalancers/features/VirtualIPAsyncApi.java @@ -0,0 +1,90 @@ +/** + * 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.rackspace.cloudloadbalancers.features; + +import javax.ws.rs.Consumes; +import javax.ws.rs.DELETE; +import javax.ws.rs.GET; +import javax.ws.rs.POST; +import javax.ws.rs.Path; +import javax.ws.rs.PathParam; +import javax.ws.rs.QueryParam; +import javax.ws.rs.core.MediaType; + +import org.jclouds.Fallbacks.EmptyPagedIterableOnNotFoundOr404; +import org.jclouds.Fallbacks.FalseOnNotFoundOr404; +import org.jclouds.Fallbacks.NullOnNotFoundOr404; +import org.jclouds.openstack.keystone.v2_0.filters.AuthenticateRequest; +import org.jclouds.rackspace.cloudloadbalancers.domain.VirtualIP; +import org.jclouds.rackspace.cloudloadbalancers.domain.VirtualIPWithId; +import org.jclouds.rest.annotations.BinderParam; +import org.jclouds.rest.annotations.Fallback; +import org.jclouds.rest.annotations.RequestFilters; +import org.jclouds.rest.annotations.SelectJson; +import org.jclouds.rest.binders.BindToJsonPayload; + +import com.google.common.util.concurrent.ListenableFuture; + +/** + * Provides asynchronous access to Rackspace Cloud Load Balancers via their REST API. + *

+ * + * @see VirtualIPApi + * @author Everett Toews + */ +@RequestFilters(AuthenticateRequest.class) +public interface VirtualIPAsyncApi { + + /** + * @see VirtualIPApi#create(VirtualIP) + */ + @POST + @Consumes(MediaType.APPLICATION_JSON) + @Fallback(NullOnNotFoundOr404.class) + @Path("/virtualips") + ListenableFuture create(@BinderParam(BindToJsonPayload.class) VirtualIP virtualIP); + + /** + * @see VirtualIPApi#list() + */ + @GET + @Consumes(MediaType.APPLICATION_JSON) + @Fallback(EmptyPagedIterableOnNotFoundOr404.class) + @SelectJson("virtualIps") + @Path("/virtualips") + ListenableFuture> list(); + + /** + * @see VirtualIPApi#remove(int) + */ + @DELETE + @Fallback(FalseOnNotFoundOr404.class) + @Path("/virtualips/{id}") + @Consumes("*/*") + ListenableFuture remove(@PathParam("id") int id); + + /** + * @see VirtualIPApi#remove(Iterable) + */ + @DELETE + @Fallback(FalseOnNotFoundOr404.class) + @Path("/virtualips") + @Consumes("*/*") + ListenableFuture remove(@QueryParam("id") Iterable ids); +} diff --git a/apis/rackspace-cloudloadbalancers/src/main/java/org/jclouds/rackspace/cloudloadbalancers/functions/ConvertLB.java b/apis/rackspace-cloudloadbalancers/src/main/java/org/jclouds/rackspace/cloudloadbalancers/functions/ConvertLB.java index abcc96ee1d..e94bed500d 100644 --- a/apis/rackspace-cloudloadbalancers/src/main/java/org/jclouds/rackspace/cloudloadbalancers/functions/ConvertLB.java +++ b/apis/rackspace-cloudloadbalancers/src/main/java/org/jclouds/rackspace/cloudloadbalancers/functions/ConvertLB.java @@ -24,6 +24,7 @@ import javax.inject.Inject; import org.jclouds.logging.Logger; import org.jclouds.rackspace.cloudloadbalancers.domain.AccessRuleWithId; import org.jclouds.rackspace.cloudloadbalancers.domain.LoadBalancer; +import org.jclouds.rackspace.cloudloadbalancers.domain.VirtualIPWithId; import org.jclouds.rackspace.cloudloadbalancers.domain.LoadBalancer.Builder; import com.google.common.base.Function; @@ -58,7 +59,7 @@ public class ConvertLB implements Function { .timeout(lb.getTimeout()).algorithm(lb.getAlgorithm()).halfClosed(lb.isHalfClosed()) .sessionPersistenceType(lb.getSessionPersistenceType()).connectionLogging(lb.isConnectionLogging()) .connectionThrottle(lb.getConnectionThrottle()).healthMonitor(lb.getHealthMonitor()) - .metadata(lb.getMetadata()).virtualIPs(lb.virtualIps); + .metadata(lb.getMetadata()); if (lb.cluster.size() == 1) builder.clusterName(Iterables.get(lb.cluster.values(), 0)); @@ -76,6 +77,10 @@ public class ConvertLB implements Function { builder.accessRules(ImmutableSet. of()); else builder.accessRules(lb.accessList); + if (lb.virtualIps == null) + builder.virtualIPs(ImmutableSet. of()); + else + builder.virtualIPs(lb.virtualIps); return builder.build(); } diff --git a/apis/rackspace-cloudloadbalancers/src/main/java/org/jclouds/rackspace/cloudloadbalancers/functions/LB.java b/apis/rackspace-cloudloadbalancers/src/main/java/org/jclouds/rackspace/cloudloadbalancers/functions/LB.java index 3440155206..20dc3f6b3c 100644 --- a/apis/rackspace-cloudloadbalancers/src/main/java/org/jclouds/rackspace/cloudloadbalancers/functions/LB.java +++ b/apis/rackspace-cloudloadbalancers/src/main/java/org/jclouds/rackspace/cloudloadbalancers/functions/LB.java @@ -22,12 +22,12 @@ import java.util.Date; import java.util.Map; import java.util.Set; -import org.jclouds.rackspace.cloudloadbalancers.domain.LoadBalancer.Status; import org.jclouds.rackspace.cloudloadbalancers.domain.AccessRuleWithId; +import org.jclouds.rackspace.cloudloadbalancers.domain.LoadBalancer.Status; import org.jclouds.rackspace.cloudloadbalancers.domain.Node; import org.jclouds.rackspace.cloudloadbalancers.domain.SSLTermination; import org.jclouds.rackspace.cloudloadbalancers.domain.SourceAddresses; -import org.jclouds.rackspace.cloudloadbalancers.domain.VirtualIP; +import org.jclouds.rackspace.cloudloadbalancers.domain.VirtualIPWithId; import org.jclouds.rackspace.cloudloadbalancers.domain.internal.BaseLoadBalancer; import com.google.common.base.Objects; @@ -41,7 +41,7 @@ class LB extends BaseLoadBalancer { int id; int nodeCount; Status status; - Set virtualIps = Sets.newLinkedHashSet(); + Set virtualIps = Sets.newLinkedHashSet(); Map cluster = Maps.newLinkedHashMap(); Map created = Maps.newLinkedHashMap(); Map updated = Maps.newLinkedHashMap(); diff --git a/apis/rackspace-cloudloadbalancers/src/main/java/org/jclouds/rackspace/cloudloadbalancers/loadbalancer/functions/LoadBalancerToLoadBalancerMetadata.java b/apis/rackspace-cloudloadbalancers/src/main/java/org/jclouds/rackspace/cloudloadbalancers/loadbalancer/functions/LoadBalancerToLoadBalancerMetadata.java index 8d039b7453..a3a38f49ca 100644 --- a/apis/rackspace-cloudloadbalancers/src/main/java/org/jclouds/rackspace/cloudloadbalancers/loadbalancer/functions/LoadBalancerToLoadBalancerMetadata.java +++ b/apis/rackspace-cloudloadbalancers/src/main/java/org/jclouds/rackspace/cloudloadbalancers/loadbalancer/functions/LoadBalancerToLoadBalancerMetadata.java @@ -30,7 +30,7 @@ import org.jclouds.loadbalancer.domain.LoadBalancerType; import org.jclouds.loadbalancer.domain.internal.LoadBalancerMetadataImpl; import org.jclouds.location.predicates.LocationPredicates; import org.jclouds.rackspace.cloudloadbalancers.domain.LoadBalancer; -import org.jclouds.rackspace.cloudloadbalancers.domain.VirtualIP; +import org.jclouds.rackspace.cloudloadbalancers.domain.VirtualIPWithId; import com.google.common.base.Function; import com.google.common.base.Supplier; @@ -62,10 +62,10 @@ public class LoadBalancerToLoadBalancerMetadata implements Function of(), Iterables.transform(input.getVirtualIPs(), - new Function() { + new Function() { @Override - public String apply(VirtualIP arg0) { + public String apply(VirtualIPWithId arg0) { return arg0.getAddress(); } diff --git a/apis/rackspace-cloudloadbalancers/src/test/java/org/jclouds/rackspace/cloudloadbalancers/features/VirtualIPApiExpectTest.java b/apis/rackspace-cloudloadbalancers/src/test/java/org/jclouds/rackspace/cloudloadbalancers/features/VirtualIPApiExpectTest.java new file mode 100644 index 0000000000..62f792adb7 --- /dev/null +++ b/apis/rackspace-cloudloadbalancers/src/test/java/org/jclouds/rackspace/cloudloadbalancers/features/VirtualIPApiExpectTest.java @@ -0,0 +1,99 @@ +/** + * 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.rackspace.cloudloadbalancers.features; + +import static org.testng.Assert.assertEquals; + +import java.net.URI; +import java.util.List; + +import javax.ws.rs.core.MediaType; + +import org.jclouds.http.HttpResponse; +import org.jclouds.rackspace.cloudloadbalancers.CloudLoadBalancersApi; +import org.jclouds.rackspace.cloudloadbalancers.domain.VirtualIP; +import org.jclouds.rackspace.cloudloadbalancers.domain.VirtualIPWithId; +import org.jclouds.rackspace.cloudloadbalancers.internal.BaseCloudLoadBalancerApiExpectTest; +import org.testng.annotations.Test; + +import com.google.common.collect.ImmutableList; + +/** + * @author Everett Toews + */ +@Test(groups = "unit") +public class VirtualIPApiExpectTest extends BaseCloudLoadBalancerApiExpectTest { + public void testListVirtualIPs() { + URI endpoint = URI.create("https://dfw.loadbalancers.api.rackspacecloud.com/v1.0/123123/loadbalancers/2000/virtualips"); + VirtualIPApi api = requestsSendResponses( + rackspaceAuthWithUsernameAndApiKey, + responseWithAccess, + authenticatedGET().endpoint(endpoint).build(), + HttpResponse.builder().statusCode(200).payload(payloadFromResource("/virtualips-list.json")).build() + ).getVirtualIPApiForZoneAndLoadBalancer("DFW", 2000); + + Iterable virtualIPs = api.list(); + assertEquals(virtualIPs, getVirtualIPs()); + } + + public void testCreateVirtualIPs() { + URI endpoint = URI.create("https://dfw.loadbalancers.api.rackspacecloud.com/v1.0/123123/loadbalancers/2000/virtualips"); + VirtualIPApi api = requestsSendResponses( + rackspaceAuthWithUsernameAndApiKey, + responseWithAccess, + authenticatedGET().method("POST").endpoint(endpoint).payload(payloadFromResource("/virtualips-create.json")).build(), + HttpResponse.builder().statusCode(200).payload(payloadFromResource("/virtualips-create-response.json")).build() + ).getVirtualIPApiForZoneAndLoadBalancer("DFW", 2000); + + api.create(VirtualIP.publicIPv6()); + } + + public void testRemoveSingleVirtualIP() { + URI endpoint = URI.create("https://dfw.loadbalancers.api.rackspacecloud.com/v1.0/123123/loadbalancers/2000/virtualips/23"); + VirtualIPApi api = requestsSendResponses( + rackspaceAuthWithUsernameAndApiKey, + responseWithAccess, + authenticatedGET().method("DELETE").endpoint(endpoint).replaceHeader("Accept", MediaType.WILDCARD).build(), + HttpResponse.builder().statusCode(200).build() + ).getVirtualIPApiForZoneAndLoadBalancer("DFW", 2000); + + api.remove(23); + } + + public void testRemoveManyVirtualIPs() { + URI endpoint = URI.create("https://dfw.loadbalancers.api.rackspacecloud.com/v1.0/123123/loadbalancers/2000/virtualips?id=23&id=24"); + VirtualIPApi api = requestsSendResponses( + rackspaceAuthWithUsernameAndApiKey, + responseWithAccess, + authenticatedGET().method("DELETE").endpoint(endpoint).replaceHeader("Accept", MediaType.WILDCARD).build(), + HttpResponse.builder().statusCode(200).build() + ).getVirtualIPApiForZoneAndLoadBalancer("DFW", 2000); + + List virtualIPIds = ImmutableList. of(23, 24); + api.remove(virtualIPIds); + } + + private Iterable getVirtualIPs() { + VirtualIPWithId virtualIP1 = new VirtualIPWithId(VirtualIP.Type.PUBLIC, VirtualIP.IPVersion.IPV4, 5557, "166.78.34.87"); + VirtualIPWithId virtualIP2 = new VirtualIPWithId(VirtualIP.Type.PUBLIC, VirtualIP.IPVersion.IPV6, 9076419, "2001:4800:7901:0000:9a32:3c2a:0000:0001"); + VirtualIPWithId virtualIP3 = new VirtualIPWithId(VirtualIP.Type.PUBLIC, VirtualIP.IPVersion.IPV6, 9079727, "2001:4800:7901:0000:9a32:3c2a:0000:0002"); + + return ImmutableList. of(virtualIP1, virtualIP2, virtualIP3); + } +} diff --git a/apis/rackspace-cloudloadbalancers/src/test/java/org/jclouds/rackspace/cloudloadbalancers/features/VirtualIPApiLiveTest.java b/apis/rackspace-cloudloadbalancers/src/test/java/org/jclouds/rackspace/cloudloadbalancers/features/VirtualIPApiLiveTest.java new file mode 100644 index 0000000000..dcb3f1446f --- /dev/null +++ b/apis/rackspace-cloudloadbalancers/src/test/java/org/jclouds/rackspace/cloudloadbalancers/features/VirtualIPApiLiveTest.java @@ -0,0 +1,121 @@ +/** + * 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.rackspace.cloudloadbalancers.features; + +import static org.jclouds.rackspace.cloudloadbalancers.predicates.LoadBalancerPredicates.awaitAvailable; +import static org.jclouds.rackspace.cloudloadbalancers.predicates.LoadBalancerPredicates.awaitDeleted; +import static org.testng.Assert.assertEquals; +import static org.testng.Assert.assertTrue; + +import java.util.List; + +import org.jclouds.rackspace.cloudloadbalancers.domain.LoadBalancer; +import org.jclouds.rackspace.cloudloadbalancers.domain.LoadBalancerRequest; +import org.jclouds.rackspace.cloudloadbalancers.domain.NodeRequest; +import org.jclouds.rackspace.cloudloadbalancers.domain.VirtualIP; +import org.jclouds.rackspace.cloudloadbalancers.domain.VirtualIP.Type; +import org.jclouds.rackspace.cloudloadbalancers.domain.VirtualIPWithId; +import org.jclouds.rackspace.cloudloadbalancers.internal.BaseCloudLoadBalancersApiLiveTest; +import org.testng.annotations.AfterGroups; +import org.testng.annotations.BeforeGroups; +import org.testng.annotations.Test; + +import com.google.common.collect.ImmutableList; +import com.google.common.collect.Iterables; +import com.google.common.collect.Iterators; + +/** + * @author Everett Toews + */ +@Test(groups = "live", singleThreaded = true, testName = "VirtualIPApiLiveTest") +public class VirtualIPApiLiveTest extends BaseCloudLoadBalancersApiLiveTest { + private LoadBalancer lb; + private String zone; + + @Override + @BeforeGroups(groups = { "live" }) + public void setupContext() { + super.setupContext(); + + new VirtualIPWithId(VirtualIP.Type.PUBLIC, VirtualIP.IPVersion.IPV4, 1000, "206.10.10.210"); + new VirtualIPWithId(VirtualIP.Type.PUBLIC, VirtualIP.IPVersion.IPV6, 1001, "2001:4800:7901:0000:9a32:3c2a:0000:0001"); + } + + public void testCreateLoadBalancer() { + NodeRequest nodeRequest = NodeRequest.builder().address("192.168.1.1").port(8080).build(); + LoadBalancerRequest lbRequest = LoadBalancerRequest.builder() + .name(prefix+"-jclouds").protocol("HTTP").port(80).virtualIPType(Type.PUBLIC).node(nodeRequest).build(); + + zone = Iterables.getFirst(clbApi.getConfiguredZones(), null); + lb = clbApi.getLoadBalancerApiForZone(zone).create(lbRequest); + + assertTrue(awaitAvailable(clbApi.getLoadBalancerApiForZone(zone)).apply(lb)); + } + + @Test(dependsOnMethods = "testCreateLoadBalancer") + public void testCreateVirtualIPs() throws Exception { + clbApi.getVirtualIPApiForZoneAndLoadBalancer(zone, lb.getId()).create(VirtualIP.publicIPv6()); + assertTrue(awaitAvailable(clbApi.getLoadBalancerApiForZone(zone)).apply(lb)); + clbApi.getVirtualIPApiForZoneAndLoadBalancer(zone, lb.getId()).create(VirtualIP.publicIPv6()); + assertTrue(awaitAvailable(clbApi.getLoadBalancerApiForZone(zone)).apply(lb)); + clbApi.getVirtualIPApiForZoneAndLoadBalancer(zone, lb.getId()).create(VirtualIP.publicIPv6()); + assertTrue(awaitAvailable(clbApi.getLoadBalancerApiForZone(zone)).apply(lb)); + + Iterable actualVirtualIPs = clbApi.getVirtualIPApiForZoneAndLoadBalancer(zone, lb.getId()).list(); + + assertEquals(Iterators.size(actualVirtualIPs.iterator()), 5); + } + + @Test(dependsOnMethods = "testCreateVirtualIPs") + public void testRemoveSingleVirtualIP() throws Exception { + Iterable actualVirtualIPs = clbApi.getVirtualIPApiForZoneAndLoadBalancer(zone, lb.getId()).list(); + VirtualIPWithId removedVirtualIP = Iterables.getFirst(actualVirtualIPs, null); + + assertTrue(clbApi.getVirtualIPApiForZoneAndLoadBalancer(zone, lb.getId()).remove(removedVirtualIP.getId())); + assertTrue(awaitAvailable(clbApi.getLoadBalancerApiForZone(zone)).apply(lb)); + + actualVirtualIPs = clbApi.getVirtualIPApiForZoneAndLoadBalancer(zone, lb.getId()).list(); + + assertEquals(Iterators.size(actualVirtualIPs.iterator()), 4); + } + + @Test(dependsOnMethods = "testRemoveSingleVirtualIP") + public void testRemoveManyVirtualIPs() throws Exception { + Iterable actualVirtualIPs = clbApi.getVirtualIPApiForZoneAndLoadBalancer(zone, lb.getId()).list(); + VirtualIPWithId removedVirtualIP1 = Iterables.getFirst(actualVirtualIPs, null); + VirtualIPWithId removedVirtualIP2 = Iterables.getLast(actualVirtualIPs); + List removedVirtualIPIds = ImmutableList. of(removedVirtualIP1.getId(), removedVirtualIP2.getId()); + + assertTrue(clbApi.getVirtualIPApiForZoneAndLoadBalancer(zone, lb.getId()).remove(removedVirtualIPIds)); + assertTrue(awaitAvailable(clbApi.getLoadBalancerApiForZone(zone)).apply(lb)); + + actualVirtualIPs = clbApi.getVirtualIPApiForZoneAndLoadBalancer(zone, lb.getId()).list(); + + assertEquals(Iterators.size(actualVirtualIPs.iterator()), 2); + } + + @Override + @AfterGroups(groups = "live") + protected void tearDownContext() { + assertTrue(awaitAvailable(clbApi.getLoadBalancerApiForZone(zone)).apply(lb)); + clbApi.getLoadBalancerApiForZone(zone).remove(lb.getId()); + assertTrue(awaitDeleted(clbApi.getLoadBalancerApiForZone(zone)).apply(lb)); + super.tearDownContext(); + } +} diff --git a/apis/rackspace-cloudloadbalancers/src/test/java/org/jclouds/rackspace/cloudloadbalancers/functions/ParseLoadBalancerTest.java b/apis/rackspace-cloudloadbalancers/src/test/java/org/jclouds/rackspace/cloudloadbalancers/functions/ParseLoadBalancerTest.java index 0284e02d5c..198db8d46a 100644 --- a/apis/rackspace-cloudloadbalancers/src/test/java/org/jclouds/rackspace/cloudloadbalancers/functions/ParseLoadBalancerTest.java +++ b/apis/rackspace-cloudloadbalancers/src/test/java/org/jclouds/rackspace/cloudloadbalancers/functions/ParseLoadBalancerTest.java @@ -33,7 +33,7 @@ import org.jclouds.rackspace.cloudloadbalancers.domain.Node; import org.jclouds.rackspace.cloudloadbalancers.domain.SSLTermination; import org.jclouds.rackspace.cloudloadbalancers.domain.SourceAddresses; import org.jclouds.rackspace.cloudloadbalancers.domain.VirtualIP; -import org.jclouds.rackspace.cloudloadbalancers.domain.VirtualIP.IPVersion; +import org.jclouds.rackspace.cloudloadbalancers.domain.VirtualIPWithId; import org.jclouds.rackspace.cloudloadbalancers.domain.internal.BaseLoadBalancer.Algorithm; import org.jclouds.rackspace.cloudloadbalancers.domain.internal.BaseLoadBalancer.SessionPersistenceType; import org.testng.annotations.Test; @@ -79,8 +79,8 @@ public class ParseLoadBalancerTest extends BaseItemParserTest { new AccessRuleWithId(22215, "1.2.3.4/32", AccessRule.Type.DENY), new AccessRuleWithId(22217, "12.0.0.0/8", AccessRule.Type.ALLOW))) .virtualIPs(ImmutableSet.of( - VirtualIP.builder().id(1000).address("206.10.10.210").type(VirtualIP.Type.PUBLIC).ipVersion(IPVersion.IPV4).build(), - VirtualIP.builder().id(1001).address("2001:4800:7901:0000:9a32:3c2a:0000:0001").type(VirtualIP.Type.PUBLIC).ipVersion(IPVersion.IPV6).build())) + new VirtualIPWithId(VirtualIP.Type.PUBLIC, VirtualIP.IPVersion.IPV4, 1000, "206.10.10.210"), + new VirtualIPWithId(VirtualIP.Type.PUBLIC, VirtualIP.IPVersion.IPV6, 1001, "2001:4800:7901:0000:9a32:3c2a:0000:0001"))) .nodes(ImmutableSet.of( Node.builder().id(1041).address("10.1.1.1").port(80).condition(Node.Condition.ENABLED).status(Node.Status.ONLINE).build(), Node.builder().id(1411).address("10.1.1.2").port(80).condition(Node.Condition.ENABLED).status(Node.Status.ONLINE).build())) diff --git a/apis/rackspace-cloudloadbalancers/src/test/java/org/jclouds/rackspace/cloudloadbalancers/functions/ParseLoadBalancersTest.java b/apis/rackspace-cloudloadbalancers/src/test/java/org/jclouds/rackspace/cloudloadbalancers/functions/ParseLoadBalancersTest.java index 6891d8a070..aeb00e5195 100644 --- a/apis/rackspace-cloudloadbalancers/src/test/java/org/jclouds/rackspace/cloudloadbalancers/functions/ParseLoadBalancersTest.java +++ b/apis/rackspace-cloudloadbalancers/src/test/java/org/jclouds/rackspace/cloudloadbalancers/functions/ParseLoadBalancersTest.java @@ -27,6 +27,7 @@ import org.jclouds.http.HttpResponse; import org.jclouds.json.BaseIterableWithMarkerParserTest; import org.jclouds.rackspace.cloudloadbalancers.domain.LoadBalancer; import org.jclouds.rackspace.cloudloadbalancers.domain.LoadBalancer.Status; +import org.jclouds.rackspace.cloudloadbalancers.domain.VirtualIPWithId; import org.jclouds.rackspace.cloudloadbalancers.domain.internal.BaseLoadBalancer.Algorithm; import org.jclouds.rackspace.cloudloadbalancers.domain.VirtualIP; import org.testng.annotations.Test; @@ -57,8 +58,7 @@ public class ParseLoadBalancersTest extends BaseIterableWithMarkerParserTest