From 495f78d8ce56e299f5304e3ffd084430709b1fff Mon Sep 17 00:00:00 2001 From: Everett Toews Date: Thu, 24 Jan 2013 16:33:52 -0600 Subject: [PATCH] The Error Page API for Rackspace Cloud Load Balancers. --- .../CloudLoadBalancersApi.java | 9 ++ .../CloudLoadBalancersAsyncApi.java | 9 ++ .../CloudLoadBalancersRestClientModule.java | 5 +- .../domain/HealthMonitor.java | 5 +- .../domain/SSLTermination.java | 69 +++++++++++ .../features/ContentCachingAsyncApi.java | 2 +- .../features/ErrorPageApi.java | 47 ++++++++ .../features/ErrorPageAsyncApi.java | 84 +++++++++++++ .../functions/ParseNestedBoolean.java | 2 +- .../functions/ParseNestedString.java | 62 ++++++++++ .../features/ErrorPageApiExpectTest.java | 114 ++++++++++++++++++ .../features/ErrorPageApiLiveTest.java | 95 +++++++++++++++ .../features/HealthMonitorApiExpectTest.java | 14 ++- .../src/test/resources/errorpage.html | 9 ++ 14 files changed, 520 insertions(+), 6 deletions(-) create mode 100644 apis/rackspace-cloudloadbalancers/src/main/java/org/jclouds/rackspace/cloudloadbalancers/features/ErrorPageApi.java create mode 100644 apis/rackspace-cloudloadbalancers/src/main/java/org/jclouds/rackspace/cloudloadbalancers/features/ErrorPageAsyncApi.java create mode 100644 apis/rackspace-cloudloadbalancers/src/main/java/org/jclouds/rackspace/cloudloadbalancers/functions/ParseNestedString.java create mode 100644 apis/rackspace-cloudloadbalancers/src/test/java/org/jclouds/rackspace/cloudloadbalancers/features/ErrorPageApiExpectTest.java create mode 100644 apis/rackspace-cloudloadbalancers/src/test/java/org/jclouds/rackspace/cloudloadbalancers/features/ErrorPageApiLiveTest.java create mode 100644 apis/rackspace-cloudloadbalancers/src/test/resources/errorpage.html 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 ef6206d4bc..cd43c862a6 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.ConnectionApi; import org.jclouds.rackspace.cloudloadbalancers.features.ContentCachingApi; +import org.jclouds.rackspace.cloudloadbalancers.features.ErrorPageApi; import org.jclouds.rackspace.cloudloadbalancers.features.HealthMonitorApi; import org.jclouds.rackspace.cloudloadbalancers.features.LoadBalancerApi; import org.jclouds.rackspace.cloudloadbalancers.features.NodeApi; @@ -124,4 +125,12 @@ public interface CloudLoadBalancersApi { @Path("/loadbalancers/{lbId}") SSLTerminationApi getSSLTerminationApiForZoneAndLoadBalancer( @EndpointParam(parser = ZoneToEndpoint.class) @Nullable String zone, @PathParam("lbId") int lbId); + + /** + * Provides synchronous access to Error Page features. + */ + @Delegate + @Path("/loadbalancers/{lbId}") + ErrorPageApi getErrorPageApiForZoneAndLoadBalancer( + @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 7871cbdd19..82a488923c 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 @@ -29,6 +29,7 @@ import org.jclouds.location.functions.ZoneToEndpoint; import org.jclouds.rackspace.cloudloadbalancers.features.AccessRuleAsyncApi; import org.jclouds.rackspace.cloudloadbalancers.features.ConnectionAsyncApi; import org.jclouds.rackspace.cloudloadbalancers.features.ContentCachingAsyncApi; +import org.jclouds.rackspace.cloudloadbalancers.features.ErrorPageAsyncApi; import org.jclouds.rackspace.cloudloadbalancers.features.HealthMonitorAsyncApi; import org.jclouds.rackspace.cloudloadbalancers.features.LoadBalancerAsyncApi; import org.jclouds.rackspace.cloudloadbalancers.features.NodeAsyncApi; @@ -125,4 +126,12 @@ public interface CloudLoadBalancersAsyncApi { @Path("/loadbalancers/{lbId}") SSLTerminationAsyncApi getSSLTerminationApiForZoneAndLoadBalancer( @EndpointParam(parser = ZoneToEndpoint.class) @Nullable String zone, @PathParam("lbId") int lbId); + + /** + * Provides asynchronous access to Error Page features. + */ + @Delegate + @Path("/loadbalancers/{lbId}") + ErrorPageAsyncApi getErrorPageApiForZoneAndLoadBalancer( + @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 2c3c6860e7..d9be64f71b 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.ConnectionApi; import org.jclouds.rackspace.cloudloadbalancers.features.ConnectionAsyncApi; import org.jclouds.rackspace.cloudloadbalancers.features.ContentCachingApi; import org.jclouds.rackspace.cloudloadbalancers.features.ContentCachingAsyncApi; +import org.jclouds.rackspace.cloudloadbalancers.features.ErrorPageApi; +import org.jclouds.rackspace.cloudloadbalancers.features.ErrorPageAsyncApi; import org.jclouds.rackspace.cloudloadbalancers.features.HealthMonitorApi; import org.jclouds.rackspace.cloudloadbalancers.features.HealthMonitorAsyncApi; import org.jclouds.rackspace.cloudloadbalancers.features.LoadBalancerAsyncApi; @@ -55,7 +57,7 @@ import com.google.common.collect.ImmutableMap; import com.google.inject.assistedinject.FactoryModuleBuilder; /** - * Configures theRackspace Cloud Load Balancers connection. + * Configures the Rackspace Cloud Load Balancers connection. * * @author Adrian Cole */ @@ -73,6 +75,7 @@ public class CloudLoadBalancersRestClientModule extends .put(SessionPersistenceApi.class, SessionPersistenceAsyncApi.class) .put(ContentCachingApi.class, ContentCachingAsyncApi.class) .put(SSLTerminationApi.class, SSLTerminationAsyncApi.class) + .put(ErrorPageApi.class, ErrorPageAsyncApi.class) .build(); public CloudLoadBalancersRestClientModule() { diff --git a/apis/rackspace-cloudloadbalancers/src/main/java/org/jclouds/rackspace/cloudloadbalancers/domain/HealthMonitor.java b/apis/rackspace-cloudloadbalancers/src/main/java/org/jclouds/rackspace/cloudloadbalancers/domain/HealthMonitor.java index d42a94bc90..9c5960a3cc 100644 --- a/apis/rackspace-cloudloadbalancers/src/main/java/org/jclouds/rackspace/cloudloadbalancers/domain/HealthMonitor.java +++ b/apis/rackspace-cloudloadbalancers/src/main/java/org/jclouds/rackspace/cloudloadbalancers/domain/HealthMonitor.java @@ -71,7 +71,8 @@ public class HealthMonitor { if (type.equals(Type.CONNECT)) throw new IllegalArgumentException("Only delay, timeout, and attemptsBeforeDeactivation must be set."); else - throw new IllegalArgumentException("At least delay, timeout, attemptsBeforeDeactivation, and path must be set."); + throw new IllegalArgumentException("At least delay, timeout, attemptsBeforeDeactivation, path and " + + "one or both of bodyRegex and statusRegex must be set."); } public Type getType() { @@ -116,7 +117,7 @@ public class HealthMonitor { return required && !path.isPresent() && !statusRegex.isPresent() && !bodyRegex.isPresent() && !hostHeader.isPresent(); else - return required && path.isPresent(); + return required && path.isPresent() && (statusRegex.isPresent() || bodyRegex.isPresent()); } @Override diff --git a/apis/rackspace-cloudloadbalancers/src/main/java/org/jclouds/rackspace/cloudloadbalancers/domain/SSLTermination.java b/apis/rackspace-cloudloadbalancers/src/main/java/org/jclouds/rackspace/cloudloadbalancers/domain/SSLTermination.java index ce626c92f6..26f5474764 100644 --- a/apis/rackspace-cloudloadbalancers/src/main/java/org/jclouds/rackspace/cloudloadbalancers/domain/SSLTermination.java +++ b/apis/rackspace-cloudloadbalancers/src/main/java/org/jclouds/rackspace/cloudloadbalancers/domain/SSLTermination.java @@ -55,6 +55,75 @@ import com.google.common.base.Optional; * decrypted traffic will be sent in clear text over the public internet to the external node(s) and will no longer * be secure. * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + *
+ * Optional SSL Attributes + *
Optional SSL AttributesNon-SSL TrafficSSL Traffic
enabled = true (default)YesYes
enabled = falseYesNo
secureTrafficOnly = trueNoYes
secureTrafficOnly = false (default)YesYes
+ *

enabled = true

+ *

secureTrafficOnly = true

+ *
NoYes
+ *

enabled = true

+ *

secureTrafficOnly = false

+ *
YesYes
+ *

enabled = false

+ *

secureTrafficOnly = false

+ *
YesNo
+ *

enabled = false

+ *

secureTrafficOnly = true

+ *
YesNo
+ * + * * @author Everett Toews */ public class SSLTermination { diff --git a/apis/rackspace-cloudloadbalancers/src/main/java/org/jclouds/rackspace/cloudloadbalancers/features/ContentCachingAsyncApi.java b/apis/rackspace-cloudloadbalancers/src/main/java/org/jclouds/rackspace/cloudloadbalancers/features/ContentCachingAsyncApi.java index 5e1087fc4a..d0693bb5ff 100644 --- a/apis/rackspace-cloudloadbalancers/src/main/java/org/jclouds/rackspace/cloudloadbalancers/features/ContentCachingAsyncApi.java +++ b/apis/rackspace-cloudloadbalancers/src/main/java/org/jclouds/rackspace/cloudloadbalancers/features/ContentCachingAsyncApi.java @@ -41,7 +41,7 @@ import com.google.common.util.concurrent.ListenableFuture; * Provides asynchronous access to Rackspace Cloud Load Balancers via their REST API. *

* - * @see ContentCachingAsyncApi + * @see ContentCachingApi * @author Everett Toews */ @RequestFilters(AuthenticateRequest.class) diff --git a/apis/rackspace-cloudloadbalancers/src/main/java/org/jclouds/rackspace/cloudloadbalancers/features/ErrorPageApi.java b/apis/rackspace-cloudloadbalancers/src/main/java/org/jclouds/rackspace/cloudloadbalancers/features/ErrorPageApi.java new file mode 100644 index 0000000000..86f83eae3b --- /dev/null +++ b/apis/rackspace-cloudloadbalancers/src/main/java/org/jclouds/rackspace/cloudloadbalancers/features/ErrorPageApi.java @@ -0,0 +1,47 @@ +/** + * 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; + +/** + * An error page is the html file that is shown to an end user who is attempting to access a load balancer node that + * is offline/unavailable. During provisioning, every load balancer is configured with a default error page that gets + * displayed when traffic is requested for an offline node. A single custom error page may be added per account load + * balancer with an HTTP protocol. Page updates will override existing content. + *

+ * + * @see ErrorPageAsyncApi + * @author Everett Toews + */ +public interface ErrorPageApi { + /** + * Specify the HTML content for the custom error page. Must be 65536 characters or less. + */ + void create(String content); + + /** + * Get the error page HTML content. + */ + String get(); + + /** + * If a custom error page is deleted, or the load balancer is changed to a non-HTTP protocol, the default error + * page will be restored. + */ + boolean remove(); +} \ No newline at end of file diff --git a/apis/rackspace-cloudloadbalancers/src/main/java/org/jclouds/rackspace/cloudloadbalancers/features/ErrorPageAsyncApi.java b/apis/rackspace-cloudloadbalancers/src/main/java/org/jclouds/rackspace/cloudloadbalancers/features/ErrorPageAsyncApi.java new file mode 100644 index 0000000000..569ed19a7c --- /dev/null +++ b/apis/rackspace-cloudloadbalancers/src/main/java/org/jclouds/rackspace/cloudloadbalancers/features/ErrorPageAsyncApi.java @@ -0,0 +1,84 @@ +/** + * 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.VoidOnNotFoundOr404; +import org.jclouds.openstack.keystone.v2_0.filters.AuthenticateRequest; +import org.jclouds.rackspace.cloudloadbalancers.functions.ParseNestedString; +import org.jclouds.rest.annotations.Fallback; +import org.jclouds.rest.annotations.Payload; +import org.jclouds.rest.annotations.PayloadParam; +import org.jclouds.rest.annotations.RequestFilters; +import org.jclouds.rest.annotations.ResponseParser; + +import com.google.common.util.concurrent.ListenableFuture; + +/** + * Provides asynchronous access to Rackspace Cloud Load Balancers via their REST API. + *

+ * + * @see ErrorPageApi + * @author Everett Toews + */ +@RequestFilters(AuthenticateRequest.class) +public interface ErrorPageAsyncApi { + + /** + * @see ErrorPageApi#create(String) + */ + @Named("errorpage:create") + @PUT + @Consumes(MediaType.WILDCARD) + @Produces(MediaType.APPLICATION_JSON) + @Fallback(VoidOnNotFoundOr404.class) + @Payload("%7B\"errorpage\":%7B\"content\":\"{content}\"%7D%7D") + @Path("/errorpage") + ListenableFuture create(@PayloadParam("content") String content); + + /** + * @see ErrorPageApi#get() + */ + @Named("errorpage:get") + @GET + @Consumes(MediaType.APPLICATION_JSON) + @ResponseParser(ParseNestedString.class) + @Fallback(VoidOnNotFoundOr404.class) + @Path("/errorpage") + ListenableFuture get(); + + /** + * @see ErrorPageApi#remove() + */ + @Named("errorpage:remove") + @DELETE + @Consumes(MediaType.WILDCARD) + @Fallback(FalseOnNotFoundOr404.class) + @Path("/errorpage") + ListenableFuture remove(); +} 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 index a6948b7ae1..4712e272fa 100644 --- 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 @@ -50,7 +50,7 @@ public class ParseNestedBoolean implements Function, Invo Map> map = json.apply(response); if (map == null || map.size() == 0) - throw new HttpResponseException("Unexpected connection logging format returned.", null, response); + throw new HttpResponseException("Unexpected JSON format returned.", null, response); return Iterables.get(Iterables.get(map.values(), 0).values(), 0); } diff --git a/apis/rackspace-cloudloadbalancers/src/main/java/org/jclouds/rackspace/cloudloadbalancers/functions/ParseNestedString.java b/apis/rackspace-cloudloadbalancers/src/main/java/org/jclouds/rackspace/cloudloadbalancers/functions/ParseNestedString.java new file mode 100644 index 0000000000..c19c90a75b --- /dev/null +++ b/apis/rackspace-cloudloadbalancers/src/main/java/org/jclouds/rackspace/cloudloadbalancers/functions/ParseNestedString.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 ParseNestedString implements Function, InvocationContext { + + private final ParseJson>> json; + + @Inject + ParseNestedString(ParseJson>> json) { + this.json = checkNotNull(json, "json"); + } + + @Override + public String apply(HttpResponse response) { + Map> map = json.apply(response); + + if (map == null || map.size() == 0) + throw new HttpResponseException("Unexpected JSON format returned.", null, response); + + return Iterables.get(Iterables.get(map.values(), 0).values(), 0); + } + + @Override + public ParseNestedString setContext(HttpRequest request) { + return this; + } +} diff --git a/apis/rackspace-cloudloadbalancers/src/test/java/org/jclouds/rackspace/cloudloadbalancers/features/ErrorPageApiExpectTest.java b/apis/rackspace-cloudloadbalancers/src/test/java/org/jclouds/rackspace/cloudloadbalancers/features/ErrorPageApiExpectTest.java new file mode 100644 index 0000000000..7fc4bd2ee6 --- /dev/null +++ b/apis/rackspace-cloudloadbalancers/src/test/java/org/jclouds/rackspace/cloudloadbalancers/features/ErrorPageApiExpectTest.java @@ -0,0 +1,114 @@ +/** + * 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.io.IOException; +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.internal.BaseCloudLoadBalancerApiExpectTest; +import org.jclouds.util.Strings2; +import org.testng.annotations.Test; + +/** + * @author Everett Toews + */ +@Test(groups = "unit") +public class ErrorPageApiExpectTest extends BaseCloudLoadBalancerApiExpectTest { + public String contentExpected; + public String contentEscaped; + + public ErrorPageApiExpectTest() { + super(); + + contentExpected = getContentExpected(); + contentEscaped = getContentEscaped(); + } + + public void testGetErrorPage() { + URI endpoint = URI.create("https://dfw.loadbalancers.api.rackspacecloud.com/v1.0/123123/loadbalancers/2000/errorpage"); + ErrorPageApi api = requestsSendResponses( + rackspaceAuthWithUsernameAndApiKey, + responseWithAccess, + authenticatedGET().endpoint(endpoint).build(), + HttpResponse.builder() + .statusCode(200) + .payload(payloadFromStringWithContentType("{\"errorpage\":{\"content\":\"" + contentEscaped + "\"}}", MediaType.APPLICATION_JSON)) + .build() + ).getErrorPageApiForZoneAndLoadBalancer("DFW", 2000); + + String content = api.get(); + assertEquals(content, contentExpected); + } + + public void testCreateErrorPage() { + URI endpoint = URI.create("https://dfw.loadbalancers.api.rackspacecloud.com/v1.0/123123/loadbalancers/2000/errorpage"); + ErrorPageApi api = requestsSendResponses( + rackspaceAuthWithUsernameAndApiKey, + responseWithAccess, + authenticatedGET() + .method("PUT") + .endpoint(endpoint) + .replaceHeader("Accept", MediaType.WILDCARD) + .payload(payloadFromStringWithContentType("{\"errorpage\":{\"content\":\"" + contentEscaped + "\"}}", MediaType.APPLICATION_JSON)) + .build(), + HttpResponse.builder().statusCode(200).build() + ).getErrorPageApiForZoneAndLoadBalancer("DFW", 2000); + + api.create(contentEscaped); + } + + public void testRemoveErrorPage() { + URI endpoint = URI.create("https://dfw.loadbalancers.api.rackspacecloud.com/v1.0/123123/loadbalancers/2000/errorpage"); + ErrorPageApi api = requestsSendResponses( + rackspaceAuthWithUsernameAndApiKey, + responseWithAccess, + authenticatedGET().method("DELETE").endpoint(endpoint).replaceHeader("Accept", MediaType.WILDCARD).build(), + HttpResponse.builder().statusCode(200).build() + ).getErrorPageApiForZoneAndLoadBalancer("DFW", 2000); + + assertTrue(api.remove()); + } + + public static String getContentExpected() { + String contentExpected; + + try { + contentExpected = Strings2.toStringAndClose(ErrorPageApiExpectTest.class.getResourceAsStream("/errorpage.html")); + } + catch (IOException e) { + throw new RuntimeException("Could not read in /errorpage.html", e); + } + + return contentExpected; + } + + public static String getContentEscaped() { + String contentEscaped = getContentExpected().replaceAll("\"", "\\\\\""); + contentEscaped = contentEscaped.replaceAll("\n", "\\\\n"); + + return contentEscaped; + } +} diff --git a/apis/rackspace-cloudloadbalancers/src/test/java/org/jclouds/rackspace/cloudloadbalancers/features/ErrorPageApiLiveTest.java b/apis/rackspace-cloudloadbalancers/src/test/java/org/jclouds/rackspace/cloudloadbalancers/features/ErrorPageApiLiveTest.java new file mode 100644 index 0000000000..67d2239315 --- /dev/null +++ b/apis/rackspace-cloudloadbalancers/src/test/java/org/jclouds/rackspace/cloudloadbalancers/features/ErrorPageApiLiveTest.java @@ -0,0 +1,95 @@ +/** + * 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 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.BeforeGroups; +import org.testng.annotations.Test; + +import com.google.common.collect.Iterables; + +/** + * @author Everett Toews + */ +@Test(groups = "live", singleThreaded = true, testName = "ErrorPageApiLiveTest") +public class ErrorPageApiLiveTest extends BaseCloudLoadBalancersApiLiveTest { + private LoadBalancer lb; + private String zone; + private String contentExpected; + private String contentEscaped; + + @Override + @BeforeGroups(groups = { "live" }) + public void setupContext() { + super.setupContext(); + + contentExpected = ErrorPageApiExpectTest.getContentExpected(); + contentEscaped = ErrorPageApiExpectTest.getContentEscaped(); + } + + 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 testCreateAndGetErrorPage() throws Exception { + clbApi.getErrorPageApiForZoneAndLoadBalancer(zone, lb.getId()).create(contentEscaped); + assertTrue(awaitAvailable(clbApi.getLoadBalancerApiForZone(zone)).apply(lb)); + + String content = clbApi.getErrorPageApiForZoneAndLoadBalancer(zone, lb.getId()).get(); + + assertEquals(content, contentExpected); + } + + @Test(dependsOnMethods = "testCreateAndGetErrorPage") + public void testRemoveAndGetErrorPage() throws Exception { + assertTrue(clbApi.getErrorPageApiForZoneAndLoadBalancer(zone, lb.getId()).remove()); + assertTrue(awaitAvailable(clbApi.getLoadBalancerApiForZone(zone)).apply(lb)); + + String content = clbApi.getErrorPageApiForZoneAndLoadBalancer(zone, lb.getId()).get(); + + assertTrue(content.contains("Service Unavailable")); + } + + @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/HealthMonitorApiExpectTest.java b/apis/rackspace-cloudloadbalancers/src/test/java/org/jclouds/rackspace/cloudloadbalancers/features/HealthMonitorApiExpectTest.java index 8fa869bc87..865fed1fc3 100644 --- a/apis/rackspace-cloudloadbalancers/src/test/java/org/jclouds/rackspace/cloudloadbalancers/features/HealthMonitorApiExpectTest.java +++ b/apis/rackspace-cloudloadbalancers/src/test/java/org/jclouds/rackspace/cloudloadbalancers/features/HealthMonitorApiExpectTest.java @@ -117,7 +117,7 @@ public class HealthMonitorApiExpectTest extends BaseCloudLoadBalancerApiExpectTe } @Test(expectedExceptions = IllegalArgumentException.class) - public void testInvalidHTTPHealthMonitorWithUnrequired() { + public void testInvalidHTTPHealthMonitorWithoutUnrequired() { HealthMonitor.builder() .type(HealthMonitor.Type.HTTP) .delay(3599) @@ -125,6 +125,17 @@ public class HealthMonitorApiExpectTest extends BaseCloudLoadBalancerApiExpectTe .build(); } + @Test(expectedExceptions = IllegalArgumentException.class) + public void testInvalidHTTPHealthMonitorWithoutRegex() { + HealthMonitor.builder() + .type(HealthMonitor.Type.HTTP) + .delay(3599) + .timeout(30) + .attemptsBeforeDeactivation(2) + .path("/foobar") + .build(); + } + public static HealthMonitor getConnectHealthMonitor() { HealthMonitor healthMonitor = HealthMonitor.builder() .type(HealthMonitor.Type.CONNECT) @@ -143,6 +154,7 @@ public class HealthMonitorApiExpectTest extends BaseCloudLoadBalancerApiExpectTe .timeout(30) .attemptsBeforeDeactivation(2) .path("/foobar") + .bodyRegex("foo.*bar") .build(); return healthMonitor; diff --git a/apis/rackspace-cloudloadbalancers/src/test/resources/errorpage.html b/apis/rackspace-cloudloadbalancers/src/test/resources/errorpage.html new file mode 100644 index 0000000000..7714e2f441 --- /dev/null +++ b/apis/rackspace-cloudloadbalancers/src/test/resources/errorpage.html @@ -0,0 +1,9 @@ + + + + + + + These are not the pages you're looking for. + +