From 242d3e07beea9eded51cf3e049e786ec916a6a03 Mon Sep 17 00:00:00 2001 From: Everett Toews Date: Sun, 20 Jan 2013 19:50:52 -0600 Subject: [PATCH] The Connection API for Rackspace Cloud Load Balancers. --- .../CloudLoadBalancersApi.java | 9 ++ .../CloudLoadBalancersAsyncApi.java | 9 ++ .../CloudLoadBalancersRestClientModule.java | 3 + .../domain/ConnectionThrottle.java | 8 ++ .../features/ConnectionApi.java | 64 +++++++++ .../features/ConnectionAsyncApi.java | 122 ++++++++++++++++ .../functions/ParseConnectionThrottle.java | 66 +++++++++ .../functions/ParseNestedBoolean.java | 62 +++++++++ .../features/ConnectionApiExpectTest.java | 131 ++++++++++++++++++ .../features/ConnectionApiLiveTest.java | 111 +++++++++++++++ .../features/VirtualIPApiLiveTest.java | 10 -- .../resources/connectionlogging-disable.json | 1 + .../resources/connectionlogging-enable.json | 1 + .../resources/connectionthrottle-create.json | 1 + .../resources/connectionthrottle-get.json | 8 ++ core/src/main/java/org/jclouds/Fallbacks.java | 13 ++ 16 files changed, 609 insertions(+), 10 deletions(-) create mode 100644 apis/rackspace-cloudloadbalancers/src/main/java/org/jclouds/rackspace/cloudloadbalancers/features/ConnectionApi.java create mode 100644 apis/rackspace-cloudloadbalancers/src/main/java/org/jclouds/rackspace/cloudloadbalancers/features/ConnectionAsyncApi.java create mode 100644 apis/rackspace-cloudloadbalancers/src/main/java/org/jclouds/rackspace/cloudloadbalancers/functions/ParseConnectionThrottle.java create mode 100644 apis/rackspace-cloudloadbalancers/src/main/java/org/jclouds/rackspace/cloudloadbalancers/functions/ParseNestedBoolean.java create mode 100644 apis/rackspace-cloudloadbalancers/src/test/java/org/jclouds/rackspace/cloudloadbalancers/features/ConnectionApiExpectTest.java create mode 100644 apis/rackspace-cloudloadbalancers/src/test/java/org/jclouds/rackspace/cloudloadbalancers/features/ConnectionApiLiveTest.java create mode 100644 apis/rackspace-cloudloadbalancers/src/test/resources/connectionlogging-disable.json create mode 100644 apis/rackspace-cloudloadbalancers/src/test/resources/connectionlogging-enable.json create mode 100644 apis/rackspace-cloudloadbalancers/src/test/resources/connectionthrottle-create.json create mode 100644 apis/rackspace-cloudloadbalancers/src/test/resources/connectionthrottle-get.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 b3c34aebc2..45e117e9ef 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 @@ -26,6 +26,7 @@ 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.ConnectionApi; import org.jclouds.rackspace.cloudloadbalancers.features.LoadBalancerApi; import org.jclouds.rackspace.cloudloadbalancers.features.NodeApi; import org.jclouds.rackspace.cloudloadbalancers.features.VirtualIPApi; @@ -79,4 +80,12 @@ public interface CloudLoadBalancersApi { @Path("/loadbalancers/{lbId}") VirtualIPApi getVirtualIPApiForZoneAndLoadBalancer( @EndpointParam(parser = ZoneToEndpoint.class) @Nullable String zone, @PathParam("lbId") int lbId); + + /** + * Provides synchronous access to Connection features. + */ + @Delegate + @Path("/loadbalancers/{lbId}") + ConnectionApi getConnectionApiForZoneAndLoadBalancer( + @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 96119b0ce3..33db013de1 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 @@ -27,6 +27,7 @@ import org.jclouds.javax.annotation.Nullable; import org.jclouds.location.Zone; import org.jclouds.location.functions.ZoneToEndpoint; import org.jclouds.rackspace.cloudloadbalancers.features.AccessRuleAsyncApi; +import org.jclouds.rackspace.cloudloadbalancers.features.ConnectionApi; import org.jclouds.rackspace.cloudloadbalancers.features.LoadBalancerAsyncApi; import org.jclouds.rackspace.cloudloadbalancers.features.NodeAsyncApi; import org.jclouds.rackspace.cloudloadbalancers.features.VirtualIPAsyncApi; @@ -80,4 +81,12 @@ public interface CloudLoadBalancersAsyncApi { @Path("/loadbalancers/{lbId}") VirtualIPAsyncApi getVirtualIPApiForZoneAndLoadBalancer( @EndpointParam(parser = ZoneToEndpoint.class) @Nullable String zone, @PathParam("lbId") int lbId); + + /** + * Provides synchronous access to Connection features. + */ + @Delegate + @Path("/loadbalancers/{lbId}") + ConnectionApi getConnectionApiForZoneAndLoadBalancer( + @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 7b7c2d6212..435de2bc12 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 @@ -30,6 +30,8 @@ import org.jclouds.rackspace.cloudloadbalancers.CloudLoadBalancersAsyncApi; import org.jclouds.rackspace.cloudloadbalancers.CloudLoadBalancersApi; import org.jclouds.rackspace.cloudloadbalancers.features.AccessRuleApi; import org.jclouds.rackspace.cloudloadbalancers.features.AccessRuleAsyncApi; +import org.jclouds.rackspace.cloudloadbalancers.features.ConnectionApi; +import org.jclouds.rackspace.cloudloadbalancers.features.ConnectionAsyncApi; import org.jclouds.rackspace.cloudloadbalancers.features.LoadBalancerAsyncApi; import org.jclouds.rackspace.cloudloadbalancers.features.LoadBalancerApi; import org.jclouds.rackspace.cloudloadbalancers.features.NodeAsyncApi; @@ -58,6 +60,7 @@ public class CloudLoadBalancersRestClientModule extends .put(NodeApi.class, NodeAsyncApi.class) .put(AccessRuleApi.class, AccessRuleAsyncApi.class) .put(VirtualIPApi.class, VirtualIPAsyncApi.class) + .put(ConnectionApi.class, ConnectionAsyncApi.class) .build(); public CloudLoadBalancersRestClientModule() { diff --git a/apis/rackspace-cloudloadbalancers/src/main/java/org/jclouds/rackspace/cloudloadbalancers/domain/ConnectionThrottle.java b/apis/rackspace-cloudloadbalancers/src/main/java/org/jclouds/rackspace/cloudloadbalancers/domain/ConnectionThrottle.java index d44fe20903..b6290ae5e7 100644 --- a/apis/rackspace-cloudloadbalancers/src/main/java/org/jclouds/rackspace/cloudloadbalancers/domain/ConnectionThrottle.java +++ b/apis/rackspace-cloudloadbalancers/src/main/java/org/jclouds/rackspace/cloudloadbalancers/domain/ConnectionThrottle.java @@ -18,6 +18,8 @@ */ package org.jclouds.rackspace.cloudloadbalancers.domain; +import static com.google.common.base.Preconditions.checkArgument; + import com.google.common.base.Objects; import com.google.common.base.Objects.ToStringHelper; @@ -40,6 +42,8 @@ public class ConnectionThrottle { this.minConnections = minConnections; this.maxConnectionRate = maxConnectionRate; this.rateInterval = rateInterval; + checkArgument(isValid(), + "At least one of maxConnections, minConnections, maxConnectionRate, or rateInterval must be set."); } public int getMaxConnections() { @@ -57,6 +61,10 @@ public class ConnectionThrottle { public int getRateInterval() { return this.rateInterval; } + + public boolean isValid() { + return maxConnections != 0 && minConnections != 0 && maxConnectionRate != 0 && rateInterval != 0; + } @Override public int hashCode() { diff --git a/apis/rackspace-cloudloadbalancers/src/main/java/org/jclouds/rackspace/cloudloadbalancers/features/ConnectionApi.java b/apis/rackspace-cloudloadbalancers/src/main/java/org/jclouds/rackspace/cloudloadbalancers/features/ConnectionApi.java new file mode 100644 index 0000000000..4d46bd4c0b --- /dev/null +++ b/apis/rackspace-cloudloadbalancers/src/main/java/org/jclouds/rackspace/cloudloadbalancers/features/ConnectionApi.java @@ -0,0 +1,64 @@ +/** + * 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.ConnectionThrottle; + +/** + * Connection management features. + *

+ * + * @see ConnectionAsyncApi + * @author Everett Toews + */ +public interface ConnectionApi { + /** + * The connection throttling feature imposes limits on the number of connections per IP address to help mitigate + * malicious or abusive traffic to your applications. The attributes in the table that follows can be configured + * based on the traffic patterns for your sites. + */ + void createOrUpdateConnectionThrottle(ConnectionThrottle connectionThrottle); + + /** + * Get connection throttle. + */ + ConnectionThrottle getConnectionThrottle(); + + /** + * Remove connection throttle. + * + * @return true on a successful removal, false if the connection throttle was not found + */ + boolean removeConnectionThrottle(); + + /** + * Determine if the load balancer is logging connections. + */ + boolean isConnectionLogging(); + + /** + * Enable logging connections. + */ + void enableConnectionLogging(); + + /** + * Disable logging connections. + */ + void disableConnectionLogging(); +} \ No newline at end of file diff --git a/apis/rackspace-cloudloadbalancers/src/main/java/org/jclouds/rackspace/cloudloadbalancers/features/ConnectionAsyncApi.java b/apis/rackspace-cloudloadbalancers/src/main/java/org/jclouds/rackspace/cloudloadbalancers/features/ConnectionAsyncApi.java new file mode 100644 index 0000000000..7b218fc43a --- /dev/null +++ b/apis/rackspace-cloudloadbalancers/src/main/java/org/jclouds/rackspace/cloudloadbalancers/features/ConnectionAsyncApi.java @@ -0,0 +1,122 @@ +/** + * 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.inject.Named; +import javax.ws.rs.Consumes; +import javax.ws.rs.DELETE; +import javax.ws.rs.GET; +import javax.ws.rs.PUT; +import javax.ws.rs.Path; +import javax.ws.rs.Produces; +import javax.ws.rs.core.MediaType; + +import org.jclouds.Fallbacks.FalseOnNotFoundOr404; +import org.jclouds.Fallbacks.FalseOnNotFoundOr422; +import org.jclouds.Fallbacks.NullOnNotFoundOr404; +import org.jclouds.Fallbacks.VoidOnNotFoundOr404; +import org.jclouds.openstack.keystone.v2_0.filters.AuthenticateRequest; +import org.jclouds.rackspace.cloudloadbalancers.domain.ConnectionThrottle; +import org.jclouds.rackspace.cloudloadbalancers.functions.ParseConnectionThrottle; +import org.jclouds.rackspace.cloudloadbalancers.functions.ParseNestedBoolean; +import org.jclouds.rest.annotations.Fallback; +import org.jclouds.rest.annotations.Payload; +import org.jclouds.rest.annotations.RequestFilters; +import org.jclouds.rest.annotations.ResponseParser; +import org.jclouds.rest.annotations.WrapWith; + +import com.google.common.util.concurrent.ListenableFuture; + +/** + * Provides asynchronous access to Rackspace Cloud Load Balancers via their REST API. + *

+ * + * @see ConnectionApi + * @author Everett Toews + */ +@RequestFilters(AuthenticateRequest.class) +public interface ConnectionAsyncApi { + + /** + * @see ConnectionApi#createOrUpdateConnectionThrottle(ConnectionThrottle) + */ + @Named("connectionthrottle:create") + @PUT + @Consumes(MediaType.APPLICATION_JSON) + @Fallback(VoidOnNotFoundOr404.class) + @Path("/connectionthrottle") + ListenableFuture createOrUpdateConnectionThrottle( + @WrapWith("connectionThrottle") ConnectionThrottle connectionThrottle); + + /** + * @see ConnectionApi#getConnectionThrottle() + */ + @Named("connectionthrottle:get") + @GET + @Consumes(MediaType.APPLICATION_JSON) + @ResponseParser(ParseConnectionThrottle.class) + @Fallback(NullOnNotFoundOr404.class) + @Path("/connectionthrottle") + ListenableFuture getConnectionThrottle(); + + /** + * @see ConnectionApi#removeConnectionThrottle() + */ + @Named("connectionthrottle:remove") + @DELETE + @Fallback(FalseOnNotFoundOr422.class) + @Path("/connectionthrottle") + @Consumes("*/*") + ListenableFuture removeConnectionThrottle(); + + /** + * @see ConnectionApi#isConnectionLogging() + */ + @Named("connectionlogging:state") + @GET + @Consumes(MediaType.APPLICATION_JSON) + @ResponseParser(ParseNestedBoolean.class) + @Fallback(FalseOnNotFoundOr404.class) + @Path("/connectionlogging") + ListenableFuture isConnectionLogging(); + + /** + * @see ConnectionApi#enableConnectionLogging() + */ + @Named("connectionlogging:state") + @PUT + @Produces(MediaType.APPLICATION_JSON) + @Consumes(MediaType.APPLICATION_JSON) + @Fallback(VoidOnNotFoundOr404.class) + @Payload("{\"connectionLogging\":{\"enabled\":true}}") + @Path("/connectionlogging") + ListenableFuture enableConnectionLogging(); + + /** + * @see ConnectionApi#disableConnectionLogging() + */ + @Named("connectionlogging:state") + @PUT + @Produces(MediaType.APPLICATION_JSON) + @Consumes(MediaType.APPLICATION_JSON) + @Fallback(VoidOnNotFoundOr404.class) + @Payload("{\"connectionLogging\":{\"enabled\":false}}") + @Path("/connectionlogging") + ListenableFuture disableConnectionLogging(); +} diff --git a/apis/rackspace-cloudloadbalancers/src/main/java/org/jclouds/rackspace/cloudloadbalancers/functions/ParseConnectionThrottle.java b/apis/rackspace-cloudloadbalancers/src/main/java/org/jclouds/rackspace/cloudloadbalancers/functions/ParseConnectionThrottle.java new file mode 100644 index 0000000000..7850bde545 --- /dev/null +++ b/apis/rackspace-cloudloadbalancers/src/main/java/org/jclouds/rackspace/cloudloadbalancers/functions/ParseConnectionThrottle.java @@ -0,0 +1,66 @@ +/** + * 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.functions; + +import static com.google.common.base.Preconditions.checkNotNull; + +import java.util.Map; + +import javax.inject.Inject; + +import org.jclouds.http.HttpRequest; +import org.jclouds.http.HttpResponse; +import org.jclouds.http.HttpResponseException; +import org.jclouds.http.functions.ParseJson; +import org.jclouds.rackspace.cloudloadbalancers.domain.ConnectionThrottle; +import org.jclouds.rest.InvocationContext; + +import com.google.common.base.Function; +import com.google.common.collect.Iterables; + +/** + * @author Everett Toews + */ +public class ParseConnectionThrottle implements + Function, InvocationContext { + + private final ParseJson> json; + + @Inject + ParseConnectionThrottle(ParseJson> json) { + this.json = checkNotNull(json, "json"); + } + + @Override + public ConnectionThrottle apply(HttpResponse response) { + Map map = json.apply(response); + + if (map == null || map.size() == 0) + throw new HttpResponseException("Unexpected connection throttle format returned.", null, response); + + ConnectionThrottle connectionThrottle = Iterables.get(map.values(), 0); + + return connectionThrottle.isValid() ? connectionThrottle : null; + } + + @Override + public ParseConnectionThrottle setContext(HttpRequest request) { + return this; + } +} diff --git a/apis/rackspace-cloudloadbalancers/src/main/java/org/jclouds/rackspace/cloudloadbalancers/functions/ParseNestedBoolean.java b/apis/rackspace-cloudloadbalancers/src/main/java/org/jclouds/rackspace/cloudloadbalancers/functions/ParseNestedBoolean.java new file mode 100644 index 0000000000..a6948b7ae1 --- /dev/null +++ b/apis/rackspace-cloudloadbalancers/src/main/java/org/jclouds/rackspace/cloudloadbalancers/functions/ParseNestedBoolean.java @@ -0,0 +1,62 @@ +/** + * 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.functions; + +import static com.google.common.base.Preconditions.checkNotNull; + +import java.util.Map; + +import javax.inject.Inject; + +import org.jclouds.http.HttpRequest; +import org.jclouds.http.HttpResponse; +import org.jclouds.http.HttpResponseException; +import org.jclouds.http.functions.ParseJson; +import org.jclouds.rest.InvocationContext; + +import com.google.common.base.Function; +import com.google.common.collect.Iterables; + +/** + * @author Everett Toews + */ +public class ParseNestedBoolean implements Function, InvocationContext { + + private final ParseJson>> json; + + @Inject + ParseNestedBoolean(ParseJson>> json) { + this.json = checkNotNull(json, "json"); + } + + @Override + public Boolean apply(HttpResponse response) { + Map> map = json.apply(response); + + if (map == null || map.size() == 0) + throw new HttpResponseException("Unexpected connection logging format returned.", null, response); + + return Iterables.get(Iterables.get(map.values(), 0).values(), 0); + } + + @Override + public ParseNestedBoolean setContext(HttpRequest request) { + return this; + } +} diff --git a/apis/rackspace-cloudloadbalancers/src/test/java/org/jclouds/rackspace/cloudloadbalancers/features/ConnectionApiExpectTest.java b/apis/rackspace-cloudloadbalancers/src/test/java/org/jclouds/rackspace/cloudloadbalancers/features/ConnectionApiExpectTest.java new file mode 100644 index 0000000000..3ad8630065 --- /dev/null +++ b/apis/rackspace-cloudloadbalancers/src/test/java/org/jclouds/rackspace/cloudloadbalancers/features/ConnectionApiExpectTest.java @@ -0,0 +1,131 @@ +/** + * 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 static org.testng.Assert.assertTrue; + +import java.net.URI; + +import javax.ws.rs.core.MediaType; + +import org.jclouds.http.HttpResponse; +import org.jclouds.rackspace.cloudloadbalancers.CloudLoadBalancersApi; +import org.jclouds.rackspace.cloudloadbalancers.domain.ConnectionThrottle; +import org.jclouds.rackspace.cloudloadbalancers.internal.BaseCloudLoadBalancerApiExpectTest; +import org.testng.annotations.Test; + +/** + * @author Everett Toews + */ +@Test(groups = "unit") +public class ConnectionApiExpectTest extends BaseCloudLoadBalancerApiExpectTest { + public void testGetConnectionThrottle() { + URI endpoint = URI.create("https://dfw.loadbalancers.api.rackspacecloud.com/v1.0/123123/loadbalancers/2000/connectionthrottle"); + ConnectionApi api = requestsSendResponses( + rackspaceAuthWithUsernameAndApiKey, + responseWithAccess, + authenticatedGET().endpoint(endpoint).build(), + HttpResponse.builder().statusCode(200).payload(payloadFromResource("/connectionthrottle-get.json")).build() + ).getConnectionApiForZoneAndLoadBalancer("DFW", 2000); + + ConnectionThrottle connectionThrottle = api.getConnectionThrottle(); + assertEquals(connectionThrottle, getConnectionThrottle()); + } + + public void testCreateConnectionThrottle() { + URI endpoint = URI.create("https://dfw.loadbalancers.api.rackspacecloud.com/v1.0/123123/loadbalancers/2000/connectionthrottle"); + ConnectionApi api = requestsSendResponses( + rackspaceAuthWithUsernameAndApiKey, + responseWithAccess, + authenticatedGET().method("PUT").endpoint(endpoint).payload(payloadFromResource("/connectionthrottle-create.json")).build(), + HttpResponse.builder().statusCode(200).build() + ).getConnectionApiForZoneAndLoadBalancer("DFW", 2000); + + api.createOrUpdateConnectionThrottle(getConnectionThrottle()); + } + + public void testValidConnectionThrottle() { + assertTrue(getConnectionThrottle().isValid()); + } + + @Test(expectedExceptions = IllegalArgumentException.class) + public void testInvalidConnectionThrottle() { + ConnectionThrottle.builder().build(); + } + + public void testRemoveSingleVirtualIP() { + URI endpoint = URI.create("https://dfw.loadbalancers.api.rackspacecloud.com/v1.0/123123/loadbalancers/2000/connectionthrottle"); + ConnectionApi api = requestsSendResponses( + rackspaceAuthWithUsernameAndApiKey, + responseWithAccess, + authenticatedGET().method("DELETE").endpoint(endpoint).replaceHeader("Accept", MediaType.WILDCARD).build(), + HttpResponse.builder().statusCode(200).build() + ).getConnectionApiForZoneAndLoadBalancer("DFW", 2000); + + assertTrue(api.removeConnectionThrottle()); + } + + public void testIsConnectionLogging() { + URI endpoint = URI.create("https://dfw.loadbalancers.api.rackspacecloud.com/v1.0/123123/loadbalancers/2000/connectionlogging"); + ConnectionApi api = requestsSendResponses( + rackspaceAuthWithUsernameAndApiKey, + responseWithAccess, + authenticatedGET().endpoint(endpoint).build(), + HttpResponse.builder().statusCode(200).payload(payloadFromResource("/connectionlogging-enable.json")).build() + ).getConnectionApiForZoneAndLoadBalancer("DFW", 2000); + + assertTrue(api.isConnectionLogging()); + } + + public void testEnableConnectionLogging() { + URI endpoint = URI.create("https://dfw.loadbalancers.api.rackspacecloud.com/v1.0/123123/loadbalancers/2000/connectionlogging"); + ConnectionApi api = requestsSendResponses( + rackspaceAuthWithUsernameAndApiKey, + responseWithAccess, + authenticatedGET().method("PUT").endpoint(endpoint).payload(payloadFromResource("/connectionlogging-enable.json")).build(), + HttpResponse.builder().statusCode(200).build() + ).getConnectionApiForZoneAndLoadBalancer("DFW", 2000); + + api.enableConnectionLogging(); + } + + public void testDisableConnectionLogging() { + URI endpoint = URI.create("https://dfw.loadbalancers.api.rackspacecloud.com/v1.0/123123/loadbalancers/2000/connectionlogging"); + ConnectionApi api = requestsSendResponses( + rackspaceAuthWithUsernameAndApiKey, + responseWithAccess, + authenticatedGET().method("PUT").endpoint(endpoint).payload(payloadFromResource("/connectionlogging-disable.json")).build(), + HttpResponse.builder().statusCode(200).build() + ).getConnectionApiForZoneAndLoadBalancer("DFW", 2000); + + api.disableConnectionLogging(); + } + + public static ConnectionThrottle getConnectionThrottle() { + ConnectionThrottle connectionThrottle = ConnectionThrottle.builder() + .maxConnections(100) + .maxConnectionRate(100) + .minConnections(10) + .rateInterval(100) + .build(); + + return connectionThrottle; + } +} diff --git a/apis/rackspace-cloudloadbalancers/src/test/java/org/jclouds/rackspace/cloudloadbalancers/features/ConnectionApiLiveTest.java b/apis/rackspace-cloudloadbalancers/src/test/java/org/jclouds/rackspace/cloudloadbalancers/features/ConnectionApiLiveTest.java new file mode 100644 index 0000000000..66ec7d2812 --- /dev/null +++ b/apis/rackspace-cloudloadbalancers/src/test/java/org/jclouds/rackspace/cloudloadbalancers/features/ConnectionApiLiveTest.java @@ -0,0 +1,111 @@ +/** + * 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.assertFalse; +import static org.testng.Assert.assertNull; +import static org.testng.Assert.assertTrue; + +import org.jclouds.rackspace.cloudloadbalancers.domain.ConnectionThrottle; +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.Type; +import org.jclouds.rackspace.cloudloadbalancers.internal.BaseCloudLoadBalancersApiLiveTest; +import org.testng.annotations.AfterGroups; +import org.testng.annotations.Test; + +import com.google.common.collect.Iterables; + +/** + * @author Everett Toews + */ +@Test(groups = "live", singleThreaded = true, testName = "ConnectionApiLiveTest") +public class ConnectionApiLiveTest extends BaseCloudLoadBalancersApiLiveTest { + private LoadBalancer lb; + private String zone; + + 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 testCreateAndGetConnectionThrottling() throws Exception { + clbApi.getConnectionApiForZoneAndLoadBalancer(zone, lb.getId()).createOrUpdateConnectionThrottle( + ConnectionApiExpectTest.getConnectionThrottle()); + assertTrue(awaitAvailable(clbApi.getLoadBalancerApiForZone(zone)).apply(lb)); + + ConnectionThrottle connectionThrottle = + clbApi.getConnectionApiForZoneAndLoadBalancer(zone, lb.getId()).getConnectionThrottle(); + + assertEquals(connectionThrottle, ConnectionApiExpectTest.getConnectionThrottle()); + } + + @Test(dependsOnMethods = "testCreateAndGetConnectionThrottling") + public void testRemoveAndGetConnectionThrottle() throws Exception { + assertTrue(clbApi.getConnectionApiForZoneAndLoadBalancer(zone, lb.getId()).removeConnectionThrottle()); + assertTrue(awaitAvailable(clbApi.getLoadBalancerApiForZone(zone)).apply(lb)); + + ConnectionThrottle connectionThrottle = + clbApi.getConnectionApiForZoneAndLoadBalancer(zone, lb.getId()).getConnectionThrottle(); + + assertNull(connectionThrottle); + } + + @Test(dependsOnMethods = "testRemoveAndGetConnectionThrottle") + public void testEnableAndIsConnectionLogging() throws Exception { + clbApi.getConnectionApiForZoneAndLoadBalancer(zone, lb.getId()).enableConnectionLogging(); + assertTrue(awaitAvailable(clbApi.getLoadBalancerApiForZone(zone)).apply(lb)); + + boolean isConnectionLogging = + clbApi.getConnectionApiForZoneAndLoadBalancer(zone, lb.getId()).isConnectionLogging(); + + assertTrue(isConnectionLogging); + } + + @Test(dependsOnMethods = "testEnableAndIsConnectionLogging") + public void testDisableAndIsConnectionLogging() throws Exception { + clbApi.getConnectionApiForZoneAndLoadBalancer(zone, lb.getId()).disableConnectionLogging(); + assertTrue(awaitAvailable(clbApi.getLoadBalancerApiForZone(zone)).apply(lb)); + + boolean isConnectionLogging = + clbApi.getConnectionApiForZoneAndLoadBalancer(zone, lb.getId()).isConnectionLogging(); + + assertFalse(isConnectionLogging); + } + + @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/features/VirtualIPApiLiveTest.java b/apis/rackspace-cloudloadbalancers/src/test/java/org/jclouds/rackspace/cloudloadbalancers/features/VirtualIPApiLiveTest.java index dcb3f1446f..ee8e1390cc 100644 --- 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 @@ -33,7 +33,6 @@ 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; @@ -48,15 +47,6 @@ 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() diff --git a/apis/rackspace-cloudloadbalancers/src/test/resources/connectionlogging-disable.json b/apis/rackspace-cloudloadbalancers/src/test/resources/connectionlogging-disable.json new file mode 100644 index 0000000000..9b8f62c351 --- /dev/null +++ b/apis/rackspace-cloudloadbalancers/src/test/resources/connectionlogging-disable.json @@ -0,0 +1 @@ +{"connectionLogging":{"enabled":false}} \ No newline at end of file diff --git a/apis/rackspace-cloudloadbalancers/src/test/resources/connectionlogging-enable.json b/apis/rackspace-cloudloadbalancers/src/test/resources/connectionlogging-enable.json new file mode 100644 index 0000000000..db7841ff52 --- /dev/null +++ b/apis/rackspace-cloudloadbalancers/src/test/resources/connectionlogging-enable.json @@ -0,0 +1 @@ +{"connectionLogging":{"enabled":true}} \ No newline at end of file diff --git a/apis/rackspace-cloudloadbalancers/src/test/resources/connectionthrottle-create.json b/apis/rackspace-cloudloadbalancers/src/test/resources/connectionthrottle-create.json new file mode 100644 index 0000000000..028b736285 --- /dev/null +++ b/apis/rackspace-cloudloadbalancers/src/test/resources/connectionthrottle-create.json @@ -0,0 +1 @@ +{"connectionThrottle":{"maxConnections":100,"minConnections":10,"maxConnectionRate":100,"rateInterval":100}} \ No newline at end of file diff --git a/apis/rackspace-cloudloadbalancers/src/test/resources/connectionthrottle-get.json b/apis/rackspace-cloudloadbalancers/src/test/resources/connectionthrottle-get.json new file mode 100644 index 0000000000..cd0c6ec7ef --- /dev/null +++ b/apis/rackspace-cloudloadbalancers/src/test/resources/connectionthrottle-get.json @@ -0,0 +1,8 @@ +{ + "connectionThrottle": { + "maxConnections": 100, + "minConnections": 10, + "maxConnectionRate": 100, + "rateInterval": 100 + } +} \ No newline at end of file diff --git a/core/src/main/java/org/jclouds/Fallbacks.java b/core/src/main/java/org/jclouds/Fallbacks.java index 916387564b..812e7d8c79 100644 --- a/core/src/main/java/org/jclouds/Fallbacks.java +++ b/core/src/main/java/org/jclouds/Fallbacks.java @@ -19,6 +19,7 @@ package org.jclouds; import static com.google.common.base.Preconditions.checkNotNull; +import static com.google.common.base.Predicates.equalTo; import static com.google.common.base.Predicates.in; import static com.google.common.base.Throwables.propagate; import static com.google.common.primitives.Ints.asList; @@ -86,6 +87,18 @@ public final class Fallbacks { } + public static final class FalseOnNotFoundOr422 implements FutureFallback { + + @Override + public ListenableFuture create(Throwable t) { + if (containsResourceNotFoundException(checkNotNull(t, "throwable")) + || returnValueOnCodeOrNull(t, true, equalTo(422)) != null) + return immediateFuture(false); + throw propagate(t); + } + + } + /** * @author Leander Beernaert */