diff --git a/labs/elb/src/main/java/org/jclouds/elb/domain/HealthCheck.java b/labs/elb/src/main/java/org/jclouds/elb/domain/HealthCheck.java
new file mode 100644
index 0000000000..8c14160cf0
--- /dev/null
+++ b/labs/elb/src/main/java/org/jclouds/elb/domain/HealthCheck.java
@@ -0,0 +1,222 @@
+/**
+ * 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.elb.domain;
+
+import com.google.common.base.Objects;
+import com.google.common.base.Objects.ToStringHelper;
+
+/**
+ * Elastic Load Balancing routinely checks the health of each load-balanced Amazon EC2 instance
+ * based on the configurations that you specify. If Elastic Load Balancing finds an unhealthy
+ * instance, it stops sending traffic to the instance and reroutes traffic to healthy instances.
+ *
+ *
+ * @see doc
+ *
+ * @author Adrian Cole
+ */
+public class HealthCheck {
+
+ public static Builder> builder() {
+ return new ConcreteBuilder();
+ }
+
+ public Builder> toBuilder() {
+ return new ConcreteBuilder().fromListener(this);
+ }
+
+ public static abstract class Builder> {
+ protected abstract T self();
+
+ protected int healthyThreshold;
+ protected int interval;
+ protected String target;
+ protected int timeout;
+ protected int unhealthyThreshold;
+
+ /**
+ * @see HealthCheck#getHealthyThreshold()
+ */
+ public T healthyThreshold(int healthyThreshold) {
+ this.healthyThreshold = healthyThreshold;
+ return self();
+ }
+
+ /**
+ * @see HealthCheck#getInterval()
+ */
+ public T interval(int interval) {
+ this.interval = interval;
+ return self();
+ }
+
+ /**
+ * @see HealthCheck#getTarget()
+ */
+ public T target(String target) {
+ this.target = target;
+ return self();
+ }
+
+ /**
+ * @see HealthCheck#getTimeout()
+ */
+ public T timeout(int timeout) {
+ this.timeout = timeout;
+ return self();
+ }
+
+ /**
+ * @see HealthCheck#getUnhealthyThreshold()
+ */
+ public T unhealthyThreshold(int unhealthyThreshold) {
+ this.unhealthyThreshold = unhealthyThreshold;
+ return self();
+ }
+
+ public HealthCheck build() {
+ return new HealthCheck(healthyThreshold, interval, target, timeout, unhealthyThreshold);
+ }
+
+ public T fromListener(HealthCheck in) {
+ return this.healthyThreshold(in.getHealthyThreshold()).interval(in.getInterval()).target(in.getTarget())
+ .timeout(in.getTimeout()).unhealthyThreshold(in.getUnhealthyThreshold());
+ }
+ }
+
+ private static class ConcreteBuilder extends Builder {
+ @Override
+ protected ConcreteBuilder self() {
+ return this;
+ }
+ }
+
+ protected final int healthyThreshold;
+ protected final int interval;
+ protected final String target;
+ protected final int timeout;
+ protected final int unhealthyThreshold;
+
+ protected HealthCheck(int healthyThreshold, int interval, String target, int timeout, int unhealthyThreshold) {
+ this.healthyThreshold = healthyThreshold;
+ this.interval = interval;
+ this.target = target;
+ this.timeout = timeout;
+ this.unhealthyThreshold = unhealthyThreshold;
+ }
+
+ /**
+ * Specifies the number of consecutive health probe successes required before moving the instance
+ * to the Healthy state.
+ */
+ public int getHealthyThreshold() {
+ return healthyThreshold;
+ }
+
+ /**
+ * Specifies the approximate interval, in seconds, between health checks of an individual
+ * instance.
+ */
+ public int getInterval() {
+ return interval;
+ }
+
+ /**
+ * Specifies the instance being checked. The timeout is either TCP, HTTP, HTTPS, or SSL. The
+ * range of valid ports is one (1) through 65535.
+ *
+ * Note
+ *
+ * TCP is the default, specified as a TCP: port pair, for example "TCP:5000". In this case a
+ * healthcheck simply attempts to open a TCP connection to the instance on the specified port.
+ * Failure to connect within the configured timeout is considered unhealthy.
+ * SSL is also specified as SSL: port pair, for example, SSL:5000.
+ *
+ * For HTTP or HTTPS timeout, the situation is different. You have to include a ping path in the
+ * string. HTTP is specified as a HTTP:port;/;PathToPing; grouping, for example
+ * "HTTP:80/weather/us/wa/seattle". In this case, a HTTP GET request is issued to the instance on
+ * the given port and path. Any answer other than "200 OK" within the timeout period is
+ * considered unhealthy.
+ *
+ * The total length of the HTTP ping target needs to be 1024 16-bit Unicode characters or less.
+ */
+ public String getTarget() {
+ return target;
+ }
+
+ /**
+ * Specifies the amount of time, in seconds, during which no response means a failed health
+ * probe.
+ *
+ * Note
This value must be less than the Interval value.
+ */
+ public int getTimeout() {
+ return timeout;
+ }
+
+ /**
+ * Specifies the number of consecutive health probe failures required before moving the instance
+ * to the Unhealthy state.
+ */
+ public int getUnhealthyThreshold() {
+ return unhealthyThreshold;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public int hashCode() {
+ return Objects.hashCode(healthyThreshold, interval, target, timeout, unhealthyThreshold);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj)
+ return true;
+ if (obj == null)
+ return false;
+ if (getClass() != obj.getClass())
+ return false;
+ HealthCheck other = (HealthCheck) obj;
+ return Objects.equal(this.healthyThreshold, other.healthyThreshold)
+ && Objects.equal(this.interval, other.interval) && Objects.equal(this.target, other.target)
+ && Objects.equal(this.timeout, other.timeout)
+ && Objects.equal(this.unhealthyThreshold, other.unhealthyThreshold);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public String toString() {
+ return string().toString();
+ }
+
+ protected ToStringHelper string() {
+ return Objects.toStringHelper(this).omitNullValues().add("healthyThreshold", healthyThreshold).add("interval",
+ interval).add("target", target).add("timeout", timeout).add("unhealthyThreshold", unhealthyThreshold);
+ }
+
+}
diff --git a/labs/elb/src/main/java/org/jclouds/elb/domain/LoadBalancer.java b/labs/elb/src/main/java/org/jclouds/elb/domain/LoadBalancer.java
index 4455dd0c36..4c8f95e891 100644
--- a/labs/elb/src/main/java/org/jclouds/elb/domain/LoadBalancer.java
+++ b/labs/elb/src/main/java/org/jclouds/elb/domain/LoadBalancer.java
@@ -99,13 +99,14 @@ public class LoadBalancer {
public static abstract class Builder> {
protected abstract T self();
- private String name;
- private Date createdTime;
- private String dnsName;
- private ImmutableSet.Builder instanceIds = ImmutableSet. builder();
- private ImmutableSet.Builder listeners = ImmutableSet. builder();
- private Optional scheme = Optional.absent();
- private Optional VPCId = Optional.absent();
+ protected String name;
+ protected Date createdTime;
+ protected String dnsName;
+ protected HealthCheck healthCheck;
+ protected ImmutableSet.Builder instanceIds = ImmutableSet. builder();
+ protected ImmutableSet.Builder listeners = ImmutableSet. builder();
+ protected Optional scheme = Optional.absent();
+ protected Optional VPCId = Optional.absent();
/**
* @see LoadBalancer#getName()
@@ -131,6 +132,14 @@ public class LoadBalancer {
return self();
}
+ /**
+ * @see LoadBalancer#getHealthCheck()
+ */
+ public T healthCheck(HealthCheck healthCheck) {
+ this.healthCheck = healthCheck;
+ return self();
+ }
+
/**
* @see LoadBalancer#getInstanceIds()
*/
@@ -180,12 +189,14 @@ public class LoadBalancer {
}
public LoadBalancer build() {
- return new LoadBalancer(name, createdTime, dnsName, instanceIds.build(), listeners.build(), scheme, VPCId);
+ return new LoadBalancer(name, createdTime, dnsName, healthCheck, instanceIds.build(), listeners.build(),
+ scheme, VPCId);
}
public T fromLoadBalancer(LoadBalancer in) {
- return this.name(in.getName()).createdTime(in.getCreatedTime()).dnsName(in.getDnsName()).instanceIds(
- in.getInstanceIds()).scheme(in.getScheme().orNull()).VPCId(in.getVPCId().orNull());
+ return this.name(in.getName()).createdTime(in.getCreatedTime()).dnsName(in.getDnsName()).healthCheck(
+ in.getHealthCheck()).instanceIds(in.getInstanceIds()).scheme(in.getScheme().orNull()).VPCId(
+ in.getVPCId().orNull());
}
}
@@ -196,19 +207,22 @@ public class LoadBalancer {
}
}
- private final String name;
- private final Date createdTime;
- private final String dnsName;
- private final Set instanceIds;
- private final Set listeners;
- private final Optional scheme;
- private final Optional VPCId;
+ protected final String name;
+ protected final Date createdTime;
+ protected final String dnsName;
+ protected final HealthCheck healthCheck;
+ protected final Set instanceIds;
+ protected final Set listeners;
+ protected final Optional scheme;
+ protected final Optional VPCId;
- protected LoadBalancer(String name, Date createdTime, String dnsName, Iterable instanceIds,
- Iterable listeners, Optional scheme, Optional VPCId) {
+ protected LoadBalancer(String name, Date createdTime, String dnsName, HealthCheck healthCheck,
+ Iterable instanceIds, Iterable listeners, Optional scheme,
+ Optional VPCId) {
this.name = name;
this.createdTime = createdTime;
this.dnsName = dnsName;
+ this.healthCheck = healthCheck;
this.instanceIds = ImmutableSet.copyOf(instanceIds);
this.listeners = ImmutableSet.copyOf(listeners);
this.scheme = scheme;
@@ -237,6 +251,13 @@ public class LoadBalancer {
return dnsName;
}
+ /**
+ * Specifies information regarding the various health probes conducted on the LoadBalancer.
+ */
+ public HealthCheck getHealthCheck() {
+ return healthCheck;
+ }
+
/**
* Provides a list of EC2 instance IDs for the LoadBalancer.
*/
@@ -295,8 +316,8 @@ public class LoadBalancer {
@Override
public String toString() {
return Objects.toStringHelper(this).omitNullValues().add("name", name).add("createdTime", createdTime).add(
- "dnsName", dnsName).add("instanceIds", instanceIds).add("listeners", listeners).add("scheme",
- scheme.orNull()).add("VPCId", VPCId.orNull()).toString();
+ "dnsName", dnsName).add("healthCheck", healthCheck).add("instanceIds", instanceIds).add("listeners",
+ listeners).add("scheme", scheme.orNull()).add("VPCId", VPCId.orNull()).toString();
}
}
diff --git a/labs/elb/src/main/java/org/jclouds/elb/xml/HealthCheckHandler.java b/labs/elb/src/main/java/org/jclouds/elb/xml/HealthCheckHandler.java
new file mode 100644
index 0000000000..7bab62e0df
--- /dev/null
+++ b/labs/elb/src/main/java/org/jclouds/elb/xml/HealthCheckHandler.java
@@ -0,0 +1,79 @@
+/**
+ * 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.elb.xml;
+
+import static org.jclouds.util.SaxUtils.currentOrNull;
+import static org.jclouds.util.SaxUtils.equalsOrSuffix;
+
+import org.jclouds.elb.domain.HealthCheck;
+import org.jclouds.http.functions.ParseSax;
+import org.xml.sax.SAXException;
+
+/**
+ * @see xml
+ *
+ * @author Adrian Cole
+ */
+public class HealthCheckHandler extends ParseSax.HandlerForGeneratedRequestWithResult {
+
+ private StringBuilder currentText = new StringBuilder();
+ private HealthCheck.Builder> builder = HealthCheck.builder();
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public HealthCheck getResult() {
+ try {
+ return builder.build();
+ } finally {
+ builder = HealthCheck.builder();
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void endElement(String uri, String name, String qName) throws SAXException {
+ if (equalsOrSuffix(qName, "HealthyThreshold")) {
+ builder.healthyThreshold(Integer.parseInt(currentOrNull(currentText)));
+ } else if (equalsOrSuffix(qName, "Interval")) {
+ builder.interval(Integer.parseInt(currentOrNull(currentText)));
+ } else if (equalsOrSuffix(qName, "Target")) {
+ builder.target(currentOrNull(currentText));
+ } else if (equalsOrSuffix(qName, "Timeout")) {
+ builder.timeout(Integer.parseInt(currentOrNull(currentText)));
+ } else if (equalsOrSuffix(qName, "UnhealthyThreshold")) {
+ builder.unhealthyThreshold(Integer.parseInt(currentOrNull(currentText)));
+ }
+ currentText = new StringBuilder();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void characters(char ch[], int start, int length) {
+ currentText.append(ch, start, length);
+ }
+
+}
diff --git a/labs/elb/src/main/java/org/jclouds/elb/xml/LoadBalancerHandler.java b/labs/elb/src/main/java/org/jclouds/elb/xml/LoadBalancerHandler.java
index c703edd823..5f8ac784b4 100644
--- a/labs/elb/src/main/java/org/jclouds/elb/xml/LoadBalancerHandler.java
+++ b/labs/elb/src/main/java/org/jclouds/elb/xml/LoadBalancerHandler.java
@@ -37,18 +37,21 @@ import org.xml.sax.SAXException;
* @author Adrian Cole
*/
public class LoadBalancerHandler extends ParseSax.HandlerForGeneratedRequestWithResult {
- private final DateService dateService;
- private final ListenerWithPoliciesHandler listenerHandler;
+ protected final DateService dateService;
+ protected final HealthCheckHandler healthCheckHandler;
+ protected final ListenerWithPoliciesHandler listenerHandler;
@Inject
- protected LoadBalancerHandler(DateService dateService, ListenerWithPoliciesHandler listenerHandler) {
+ protected LoadBalancerHandler(DateService dateService, HealthCheckHandler healthCheckHandler, ListenerWithPoliciesHandler listenerHandler) {
this.dateService = dateService;
+ this.healthCheckHandler = healthCheckHandler;
this.listenerHandler = listenerHandler;
}
private StringBuilder currentText = new StringBuilder();
private LoadBalancer.Builder> builder = LoadBalancer.builder();
+ private boolean inHealthCheck;
private boolean inListeners;
protected int memberDepth;
@@ -72,6 +75,8 @@ public class LoadBalancerHandler extends ParseSax.HandlerForGeneratedRequestWith
public void startElement(String url, String name, String qName, Attributes attributes) throws SAXException {
if (equalsOrSuffix(qName, "member")) {
memberDepth++;
+ } else if (equalsOrSuffix(qName, "HealthCheck")) {
+ inHealthCheck = true;
} else if (equalsOrSuffix(qName, "ListenerDescriptions")) {
inListeners = true;
}
@@ -90,6 +95,9 @@ public class LoadBalancerHandler extends ParseSax.HandlerForGeneratedRequestWith
memberDepth--;
} else if (equalsOrSuffix(qName, "ListenerDescriptions")) {
inListeners = false;
+ } else if (equalsOrSuffix(qName, "HealthCheck")) {
+ builder.healthCheck(healthCheckHandler.getResult());
+ inHealthCheck = false;
} else if (equalsOrSuffix(qName, "LoadBalancerName")) {
builder.name(currentOrNull(currentText));
} else if (equalsOrSuffix(qName, "CreatedTime")) {
@@ -102,6 +110,8 @@ public class LoadBalancerHandler extends ParseSax.HandlerForGeneratedRequestWith
builder.scheme(Scheme.fromValue(currentOrNull(currentText)));
} else if (equalsOrSuffix(qName, "VPCId")) {
builder.VPCId(currentOrNull(currentText));
+ } else if (inHealthCheck) {
+ healthCheckHandler.endElement(uri, name, qName);
} else if (inListeners) {
listenerHandler.endElement(uri, name, qName);
}
@@ -121,6 +131,8 @@ public class LoadBalancerHandler extends ParseSax.HandlerForGeneratedRequestWith
public void characters(char ch[], int start, int length) {
if (inListeners) {
listenerHandler.characters(ch, start, length);
+ } else if (inHealthCheck) {
+ healthCheckHandler.characters(ch, start, length);
} else {
currentText.append(ch, start, length);
}
diff --git a/labs/elb/src/test/java/org/jclouds/elb/features/LoadBalancerClientLiveTest.java b/labs/elb/src/test/java/org/jclouds/elb/features/LoadBalancerClientLiveTest.java
index 6c8feae889..836cd58714 100644
--- a/labs/elb/src/test/java/org/jclouds/elb/features/LoadBalancerClientLiveTest.java
+++ b/labs/elb/src/test/java/org/jclouds/elb/features/LoadBalancerClientLiveTest.java
@@ -38,6 +38,7 @@ public class LoadBalancerClientLiveTest extends BaseELBClientLiveTest {
checkNotNull(loadBalancer.getName(), "While Name can be null for a LoadBalancer, its Optional wrapper cannot.");
checkNotNull(loadBalancer.getCreatedTime(), "CreatedTime cannot be null for a LoadBalancer.");
checkNotNull(loadBalancer.getDnsName(), "DnsName cannot be null for a LoadBalancer.");
+ checkNotNull(loadBalancer.getHealthCheck(), "HealthCheck cannot be null for a LoadBalancer.");
checkNotNull(loadBalancer.getScheme(),
"While Scheme can be null for a LoadBalancer, its Optional wrapper cannot.");
checkNotNull(loadBalancer.getVPCId(), "While VPCId can be null for a LoadBalancer, its Optional wrapper cannot.");
diff --git a/labs/elb/src/test/java/org/jclouds/elb/parse/DescribeLoadBalancersResponseTest.java b/labs/elb/src/test/java/org/jclouds/elb/parse/DescribeLoadBalancersResponseTest.java
index 0e511a08c0..2d303ec5f7 100644
--- a/labs/elb/src/test/java/org/jclouds/elb/parse/DescribeLoadBalancersResponseTest.java
+++ b/labs/elb/src/test/java/org/jclouds/elb/parse/DescribeLoadBalancersResponseTest.java
@@ -24,6 +24,7 @@ import java.io.InputStream;
import org.jclouds.collect.PaginatedSet;
import org.jclouds.date.internal.SimpleDateFormatDateService;
+import org.jclouds.elb.domain.HealthCheck;
import org.jclouds.elb.domain.ListenerWithPolicies;
import org.jclouds.elb.domain.LoadBalancer;
import org.jclouds.elb.domain.Protocol;
@@ -58,6 +59,12 @@ public class DescribeLoadBalancersResponseTest extends BaseHandlerTest {
.name("my-load-balancer")
.createdTime(new SimpleDateFormatDateService().iso8601DateParse("2010-03-03T20:54:45.110Z"))
.dnsName("my-load-balancer-1400212309.us-east-1.elb.amazonaws.com")
+ .healthCheck(HealthCheck.builder()
+ .interval(300)
+ .target("HTTP:80/index.html")
+ .healthyThreshold(3)
+ .timeout(30)
+ .unhealthyThreshold(5).build())
.instanceIds(ImmutableSet.of("i-5b33e630", "i-8f26d7e4", "i-5933e632"))
.listener(ListenerWithPolicies.builder().protocol(Protocol.HTTP).port(80).instancePort(80).build())
.listener(ListenerWithPolicies.builder().protocol(Protocol.TCP).port(443).instancePort(443).build())
diff --git a/labs/elb/src/test/java/org/jclouds/elb/parse/GetLoadBalancerResponseTest.java b/labs/elb/src/test/java/org/jclouds/elb/parse/GetLoadBalancerResponseTest.java
index 6556e122cd..c24e0ade62 100644
--- a/labs/elb/src/test/java/org/jclouds/elb/parse/GetLoadBalancerResponseTest.java
+++ b/labs/elb/src/test/java/org/jclouds/elb/parse/GetLoadBalancerResponseTest.java
@@ -23,6 +23,7 @@ import static org.testng.Assert.assertEquals;
import java.io.InputStream;
import org.jclouds.date.internal.SimpleDateFormatDateService;
+import org.jclouds.elb.domain.HealthCheck;
import org.jclouds.elb.domain.ListenerWithPolicies;
import org.jclouds.elb.domain.LoadBalancer;
import org.jclouds.elb.domain.Protocol;
@@ -50,6 +51,7 @@ public class GetLoadBalancerResponseTest extends BaseHandlerTest {
assertEquals(result, expected);
assertEquals(result.getCreatedTime(), expected.getCreatedTime());
assertEquals(result.getDnsName(), expected.getDnsName());
+ assertEquals(result.getHealthCheck(), expected.getHealthCheck());
assertEquals(result.getScheme(), expected.getScheme());
assertEquals(result.getVPCId(), expected.getVPCId());
}
@@ -59,6 +61,12 @@ public class GetLoadBalancerResponseTest extends BaseHandlerTest {
.name("my-load-balancer")
.createdTime(new SimpleDateFormatDateService().iso8601DateParse("2010-03-03T20:54:45.110Z"))
.dnsName("my-load-balancer-1400212309.us-east-1.elb.amazonaws.com")
+ .healthCheck(HealthCheck.builder()
+ .interval(300)
+ .target("HTTP:80/index.html")
+ .healthyThreshold(3)
+ .timeout(30)
+ .unhealthyThreshold(5).build())
.instanceIds(ImmutableSet.of("i-5b33e630", "i-8f26d7e4", "i-5933e632"))
.listener(ListenerWithPolicies.builder().protocol(Protocol.HTTP).port(80).instancePort(80).build())
.listener(ListenerWithPolicies.builder().protocol(Protocol.TCP).port(443).instancePort(443).build())