mirror of https://github.com/apache/jclouds.git
Merge pull request #1242 from rackspace/rax-clb-error-page
The Error Page API for Rackspace Cloud Load Balancers.
This commit is contained in:
commit
bb670ebb89
|
@ -28,6 +28,7 @@ import org.jclouds.location.functions.ZoneToEndpoint;
|
||||||
import org.jclouds.rackspace.cloudloadbalancers.features.AccessRuleApi;
|
import org.jclouds.rackspace.cloudloadbalancers.features.AccessRuleApi;
|
||||||
import org.jclouds.rackspace.cloudloadbalancers.features.ConnectionApi;
|
import org.jclouds.rackspace.cloudloadbalancers.features.ConnectionApi;
|
||||||
import org.jclouds.rackspace.cloudloadbalancers.features.ContentCachingApi;
|
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.HealthMonitorApi;
|
||||||
import org.jclouds.rackspace.cloudloadbalancers.features.LoadBalancerApi;
|
import org.jclouds.rackspace.cloudloadbalancers.features.LoadBalancerApi;
|
||||||
import org.jclouds.rackspace.cloudloadbalancers.features.NodeApi;
|
import org.jclouds.rackspace.cloudloadbalancers.features.NodeApi;
|
||||||
|
@ -124,4 +125,12 @@ public interface CloudLoadBalancersApi {
|
||||||
@Path("/loadbalancers/{lbId}")
|
@Path("/loadbalancers/{lbId}")
|
||||||
SSLTerminationApi getSSLTerminationApiForZoneAndLoadBalancer(
|
SSLTerminationApi getSSLTerminationApiForZoneAndLoadBalancer(
|
||||||
@EndpointParam(parser = ZoneToEndpoint.class) @Nullable String zone, @PathParam("lbId") int lbId);
|
@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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,6 +29,7 @@ import org.jclouds.location.functions.ZoneToEndpoint;
|
||||||
import org.jclouds.rackspace.cloudloadbalancers.features.AccessRuleAsyncApi;
|
import org.jclouds.rackspace.cloudloadbalancers.features.AccessRuleAsyncApi;
|
||||||
import org.jclouds.rackspace.cloudloadbalancers.features.ConnectionAsyncApi;
|
import org.jclouds.rackspace.cloudloadbalancers.features.ConnectionAsyncApi;
|
||||||
import org.jclouds.rackspace.cloudloadbalancers.features.ContentCachingAsyncApi;
|
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.HealthMonitorAsyncApi;
|
||||||
import org.jclouds.rackspace.cloudloadbalancers.features.LoadBalancerAsyncApi;
|
import org.jclouds.rackspace.cloudloadbalancers.features.LoadBalancerAsyncApi;
|
||||||
import org.jclouds.rackspace.cloudloadbalancers.features.NodeAsyncApi;
|
import org.jclouds.rackspace.cloudloadbalancers.features.NodeAsyncApi;
|
||||||
|
@ -125,4 +126,12 @@ public interface CloudLoadBalancersAsyncApi {
|
||||||
@Path("/loadbalancers/{lbId}")
|
@Path("/loadbalancers/{lbId}")
|
||||||
SSLTerminationAsyncApi getSSLTerminationApiForZoneAndLoadBalancer(
|
SSLTerminationAsyncApi getSSLTerminationApiForZoneAndLoadBalancer(
|
||||||
@EndpointParam(parser = ZoneToEndpoint.class) @Nullable String zone, @PathParam("lbId") int lbId);
|
@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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -34,6 +34,8 @@ import org.jclouds.rackspace.cloudloadbalancers.features.ConnectionApi;
|
||||||
import org.jclouds.rackspace.cloudloadbalancers.features.ConnectionAsyncApi;
|
import org.jclouds.rackspace.cloudloadbalancers.features.ConnectionAsyncApi;
|
||||||
import org.jclouds.rackspace.cloudloadbalancers.features.ContentCachingApi;
|
import org.jclouds.rackspace.cloudloadbalancers.features.ContentCachingApi;
|
||||||
import org.jclouds.rackspace.cloudloadbalancers.features.ContentCachingAsyncApi;
|
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.HealthMonitorApi;
|
||||||
import org.jclouds.rackspace.cloudloadbalancers.features.HealthMonitorAsyncApi;
|
import org.jclouds.rackspace.cloudloadbalancers.features.HealthMonitorAsyncApi;
|
||||||
import org.jclouds.rackspace.cloudloadbalancers.features.LoadBalancerAsyncApi;
|
import org.jclouds.rackspace.cloudloadbalancers.features.LoadBalancerAsyncApi;
|
||||||
|
@ -55,7 +57,7 @@ import com.google.common.collect.ImmutableMap;
|
||||||
import com.google.inject.assistedinject.FactoryModuleBuilder;
|
import com.google.inject.assistedinject.FactoryModuleBuilder;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Configures theRackspace Cloud Load Balancers connection.
|
* Configures the Rackspace Cloud Load Balancers connection.
|
||||||
*
|
*
|
||||||
* @author Adrian Cole
|
* @author Adrian Cole
|
||||||
*/
|
*/
|
||||||
|
@ -73,6 +75,7 @@ public class CloudLoadBalancersRestClientModule extends
|
||||||
.put(SessionPersistenceApi.class, SessionPersistenceAsyncApi.class)
|
.put(SessionPersistenceApi.class, SessionPersistenceAsyncApi.class)
|
||||||
.put(ContentCachingApi.class, ContentCachingAsyncApi.class)
|
.put(ContentCachingApi.class, ContentCachingAsyncApi.class)
|
||||||
.put(SSLTerminationApi.class, SSLTerminationAsyncApi.class)
|
.put(SSLTerminationApi.class, SSLTerminationAsyncApi.class)
|
||||||
|
.put(ErrorPageApi.class, ErrorPageAsyncApi.class)
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
public CloudLoadBalancersRestClientModule() {
|
public CloudLoadBalancersRestClientModule() {
|
||||||
|
|
|
@ -71,7 +71,8 @@ public class HealthMonitor {
|
||||||
if (type.equals(Type.CONNECT))
|
if (type.equals(Type.CONNECT))
|
||||||
throw new IllegalArgumentException("Only delay, timeout, and attemptsBeforeDeactivation must be set.");
|
throw new IllegalArgumentException("Only delay, timeout, and attemptsBeforeDeactivation must be set.");
|
||||||
else
|
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() {
|
public Type getType() {
|
||||||
|
@ -116,7 +117,7 @@ public class HealthMonitor {
|
||||||
return required && !path.isPresent() && !statusRegex.isPresent()
|
return required && !path.isPresent() && !statusRegex.isPresent()
|
||||||
&& !bodyRegex.isPresent() && !hostHeader.isPresent();
|
&& !bodyRegex.isPresent() && !hostHeader.isPresent();
|
||||||
else
|
else
|
||||||
return required && path.isPresent();
|
return required && path.isPresent() && (statusRegex.isPresent() || bodyRegex.isPresent());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -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
|
* decrypted traffic will be sent in clear text over the public internet to the external node(s) and will no longer
|
||||||
* be secure.</li>
|
* be secure.</li>
|
||||||
* </ol>
|
* </ol>
|
||||||
|
*
|
||||||
|
* <table border="1">
|
||||||
|
* <caption>
|
||||||
|
* Optional SSL Attributes
|
||||||
|
* </caption>
|
||||||
|
* <thead>
|
||||||
|
* <tr align="center">
|
||||||
|
* <td>Optional SSL Attributes</td>
|
||||||
|
* <td>Non-SSL Traffic</td>
|
||||||
|
* <td>SSL Traffic</td>
|
||||||
|
* </tr>
|
||||||
|
* </thead>
|
||||||
|
* <tbody>
|
||||||
|
* <tr align="left">
|
||||||
|
* <td><code class="code">enabled</code> = <code class="code">true</code> (default)</td>
|
||||||
|
* <td>Yes</td>
|
||||||
|
* <td>Yes</td>
|
||||||
|
* </tr>
|
||||||
|
* <tr align="left">
|
||||||
|
* <td><code class="code">enabled</code> = <code class="code">false</code></td>
|
||||||
|
* <td>Yes</td>
|
||||||
|
* <td>No</td>
|
||||||
|
* </tr>
|
||||||
|
* <tr align="left">
|
||||||
|
* <td><code class="code">secureTrafficOnly</code> = <code class="code">true</code></td>
|
||||||
|
* <td>No</td>
|
||||||
|
* <td>Yes</td>
|
||||||
|
* </tr>
|
||||||
|
* <tr align="left">
|
||||||
|
* <td><code class="code">secureTrafficOnly</code> = <code class="code">false</code> (default)</td>
|
||||||
|
* <td>Yes</td>
|
||||||
|
* <td>Yes</td>
|
||||||
|
* </tr>
|
||||||
|
* <tr align="left">
|
||||||
|
* <td>
|
||||||
|
* <p><code class="code">enabled</code> = <code class="code">true</code></p>
|
||||||
|
* <p><code class="code">secureTrafficOnly</code> = <code class="code">true</code></p>
|
||||||
|
* </td>
|
||||||
|
* <td>No</td>
|
||||||
|
* <td>Yes</td>
|
||||||
|
* </tr>
|
||||||
|
* <tr align="left">
|
||||||
|
* <td>
|
||||||
|
* <p><code class="code">enabled</code> = <code class="code">true</code></p>
|
||||||
|
* <p><code class="code">secureTrafficOnly</code> = <code class="code">false</code></p>
|
||||||
|
* </td>
|
||||||
|
* <td>Yes</td>
|
||||||
|
* <td>Yes</td>
|
||||||
|
* </tr>
|
||||||
|
* <tr align="left">
|
||||||
|
* <td>
|
||||||
|
* <p><code class="code">enabled</code> = <code class="code">false</code></p>
|
||||||
|
* <p><code class="code">secureTrafficOnly</code> = <code class="code">false</code></p>
|
||||||
|
* </td>
|
||||||
|
* <td>Yes</td>
|
||||||
|
* <td>No</td>
|
||||||
|
* </tr>
|
||||||
|
* <tr align="left">
|
||||||
|
* <td>
|
||||||
|
* <p><code class="code">enabled</code> = <code class="code">false</code></p>
|
||||||
|
* <p><code class="code">secureTrafficOnly</code> = <code class="code">true</code></p>
|
||||||
|
* </td>
|
||||||
|
* <td>Yes</td>
|
||||||
|
* <td>No</td>
|
||||||
|
* </tr>
|
||||||
|
* </tbody>
|
||||||
|
* </table>
|
||||||
|
*
|
||||||
|
*
|
||||||
* @author Everett Toews
|
* @author Everett Toews
|
||||||
*/
|
*/
|
||||||
public class SSLTermination {
|
public class SSLTermination {
|
||||||
|
|
|
@ -41,7 +41,7 @@ import com.google.common.util.concurrent.ListenableFuture;
|
||||||
* Provides asynchronous access to Rackspace Cloud Load Balancers via their REST API.
|
* Provides asynchronous access to Rackspace Cloud Load Balancers via their REST API.
|
||||||
* <p/>
|
* <p/>
|
||||||
*
|
*
|
||||||
* @see ContentCachingAsyncApi
|
* @see ContentCachingApi
|
||||||
* @author Everett Toews
|
* @author Everett Toews
|
||||||
*/
|
*/
|
||||||
@RequestFilters(AuthenticateRequest.class)
|
@RequestFilters(AuthenticateRequest.class)
|
||||||
|
|
|
@ -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.
|
||||||
|
* <p/>
|
||||||
|
*
|
||||||
|
* @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();
|
||||||
|
}
|
|
@ -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.
|
||||||
|
* <p/>
|
||||||
|
*
|
||||||
|
* @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<Void> 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<String> get();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see ErrorPageApi#remove()
|
||||||
|
*/
|
||||||
|
@Named("errorpage:remove")
|
||||||
|
@DELETE
|
||||||
|
@Consumes(MediaType.WILDCARD)
|
||||||
|
@Fallback(FalseOnNotFoundOr404.class)
|
||||||
|
@Path("/errorpage")
|
||||||
|
ListenableFuture<Boolean> remove();
|
||||||
|
}
|
|
@ -50,7 +50,7 @@ public class ParseNestedBoolean implements Function<HttpResponse, Boolean>, Invo
|
||||||
Map<String, Map<String, Boolean>> map = json.apply(response);
|
Map<String, Map<String, Boolean>> map = json.apply(response);
|
||||||
|
|
||||||
if (map == null || map.size() == 0)
|
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);
|
return Iterables.get(Iterables.get(map.values(), 0).values(), 0);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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<HttpResponse, String>, InvocationContext<ParseNestedString> {
|
||||||
|
|
||||||
|
private final ParseJson<Map<String, Map<String, String>>> json;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
ParseNestedString(ParseJson<Map<String, Map<String, String>>> json) {
|
||||||
|
this.json = checkNotNull(json, "json");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String apply(HttpResponse response) {
|
||||||
|
Map<String, Map<String, String>> 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;
|
||||||
|
}
|
||||||
|
}
|
|
@ -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<CloudLoadBalancersApi> {
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
|
@ -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();
|
||||||
|
}
|
||||||
|
}
|
|
@ -117,7 +117,7 @@ public class HealthMonitorApiExpectTest extends BaseCloudLoadBalancerApiExpectTe
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test(expectedExceptions = IllegalArgumentException.class)
|
@Test(expectedExceptions = IllegalArgumentException.class)
|
||||||
public void testInvalidHTTPHealthMonitorWithUnrequired() {
|
public void testInvalidHTTPHealthMonitorWithoutUnrequired() {
|
||||||
HealthMonitor.builder()
|
HealthMonitor.builder()
|
||||||
.type(HealthMonitor.Type.HTTP)
|
.type(HealthMonitor.Type.HTTP)
|
||||||
.delay(3599)
|
.delay(3599)
|
||||||
|
@ -125,6 +125,17 @@ public class HealthMonitorApiExpectTest extends BaseCloudLoadBalancerApiExpectTe
|
||||||
.build();
|
.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() {
|
public static HealthMonitor getConnectHealthMonitor() {
|
||||||
HealthMonitor healthMonitor = HealthMonitor.builder()
|
HealthMonitor healthMonitor = HealthMonitor.builder()
|
||||||
.type(HealthMonitor.Type.CONNECT)
|
.type(HealthMonitor.Type.CONNECT)
|
||||||
|
@ -143,6 +154,7 @@ public class HealthMonitorApiExpectTest extends BaseCloudLoadBalancerApiExpectTe
|
||||||
.timeout(30)
|
.timeout(30)
|
||||||
.attemptsBeforeDeactivation(2)
|
.attemptsBeforeDeactivation(2)
|
||||||
.path("/foobar")
|
.path("/foobar")
|
||||||
|
.bodyRegex("foo.*bar")
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
return healthMonitor;
|
return healthMonitor;
|
||||||
|
|
|
@ -0,0 +1,9 @@
|
||||||
|
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 3.2//EN">
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title></title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
These are not the pages you're looking for.
|
||||||
|
</body>
|
||||||
|
</html>
|
Loading…
Reference in New Issue