Repository: aries-containers Updated Branches: refs/heads/master fcee2cdd2 -> 6289b71d1
Add support for health checks to the Service Configuration API. Project: http://git-wip-us.apache.org/repos/asf/aries-containers/repo Commit: http://git-wip-us.apache.org/repos/asf/aries-containers/commit/6289b71d Tree: http://git-wip-us.apache.org/repos/asf/aries-containers/tree/6289b71d Diff: http://git-wip-us.apache.org/repos/asf/aries-containers/diff/6289b71d Branch: refs/heads/master Commit: 6289b71d1e57ccfaea1e23fb42dd033652ace2d5 Parents: fcee2cd Author: David Bosschaert <[email protected]> Authored: Thu Jun 15 14:23:24 2017 +0100 Committer: David Bosschaert <[email protected]> Committed: Thu Jun 15 14:23:24 2017 +0100 ---------------------------------------------------------------------- .../apache/aries/containers/HealthCheck.java | 255 +++++++++++++++++++ .../apache/aries/containers/ServiceConfig.java | 41 ++- .../aries/containers/api/ServiceConfigTest.java | 11 + 3 files changed, 299 insertions(+), 8 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/aries-containers/blob/6289b71d/containers-api/src/main/java/org/apache/aries/containers/HealthCheck.java ---------------------------------------------------------------------- diff --git a/containers-api/src/main/java/org/apache/aries/containers/HealthCheck.java b/containers-api/src/main/java/org/apache/aries/containers/HealthCheck.java new file mode 100644 index 0000000..5d492f8 --- /dev/null +++ b/containers-api/src/main/java/org/apache/aries/containers/HealthCheck.java @@ -0,0 +1,255 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF 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.apache.aries.containers; + +import org.osgi.annotation.versioning.ProviderType; + +/** + * Define a health check. Most container system support health checks of some + * sort. Health checks are provided to a Service Manager via the Service Configuration. + * + * @see ServiceConfig + */ +@ProviderType +public class HealthCheck { + /** + * Supported health check types, The parameters for health checks are + * specified in the parameters member. + */ + public enum Type { + /** + * Health check defined as a HTTP request. The request should return + * a return code between 200 and 399. {@link HealthCheck#getParameters()} + * provides the URL for the HTTP request. + */ + HTTP, + + /** + * Health check defined as a HTTPS request. The request should return + * a return code between 200 and 399. {@link HealthCheck#getParameters()} + * provides the URL for the HTTP request. + */ + HTTPS, + + /** + * Health check defined as a TCP port connection. If opening a TCP port to + * succeeds the health check passes. The port to connect to is specified + * via {@link HealthCheck#getParameters()}. An port index is specified via + * {@code $PORT0}, {@code $PORT1} etc. An actual port is specified as a number, + * e.g. {@code 8080}. + */ + TCP, + + /** + * Health check defined as a command to be executed locally in the container to + * determine that the container is healthy. The command should have return {@code 0} + * to indicate that its healthy. The actual command to execute is + * available from {@link HealthCheck#getParameters()}. + */ + COMMAND, + + /** + * This type of health check can be used for proprietary health checks that are not + * covered by other types. + */ + OTHER }; + + private final String parameters; + private final Type type; + private final int gracePeriod; + private final int interval; + private final int timeout; + private final int maxFailures; + + private HealthCheck(String parameters, Type type, int gracePeriod, int interval, + int timeout, int maxFailures) { + this.parameters = parameters; + this.type = type; + this.gracePeriod = gracePeriod; + this.interval = interval; + this.timeout = timeout; + this.maxFailures = maxFailures; + } + + /** + * @return The health check type. + */ + public Type getType() { + return type; + } + + /** + * @return The grace period in seconds. Health checks are ignored for the duration of the grace + * period until the container is healthy. + */ + public int getGracePeriod() { + return gracePeriod; + } + + /** + * @return The interval at which health checks are evaluated, specified in seconds. + */ + public int getInterval() { + return interval; + } + + /** + * @return The number of failed health check after which a task will be killed. + */ + public int getMaxFailures() { + return maxFailures; + } + + /** + * @return The parameters for a given health check, such as the HTTP URL or command line. + */ + public String getParameters() { + return parameters; + } + + /** + * @return The number of seconds after which a health check is considered a failure, regardless + * of the obtained result. + */ + public int getTimeout() { + return timeout; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((parameters == null) ? 0 : parameters.hashCode()); + result = prime * result + gracePeriod; + result = prime * result + interval; + result = prime * result + maxFailures; + result = prime * result + timeout; + result = prime * result + ((type == null) ? 0 : type.hashCode()); + return result; + } + + @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; + if (parameters == null) { + if (other.parameters != null) + return false; + } else if (!parameters.equals(other.parameters)) + return false; + if (gracePeriod != other.gracePeriod) + return false; + if (interval != other.interval) + return false; + if (maxFailures != other.maxFailures) + return false; + if (timeout != other.timeout) + return false; + if (type == null) { + if (other.type != null) + return false; + } else if (!type.equals(other.type)) + return false; + return true; + } + + /** + * Create a health check builder. + * @param type The type of health check. + * @return A health check builder. + */ + public static Builder builder(Type type) { + return new Builder(type); + } + + /** + * A builder for health checks. + */ + public static class Builder { + private String parameters; + private final Type type; + private int gracePeriod = 300; + private int interval = 60; + private int timeout = 20; + private int maxFailures = 3; + + Builder(Type type) { + this.type = type; + } + + /** + * Specify the parameters for the health check, such as the HTTP URL. + * @param parameters The parameters for this health check. + * @return the current builder for further building. + */ + public Builder parameters(String parameters) { + this.parameters = parameters; + return this; + } + + /** + * Specify the grace period to use. + * @param gp The grace period in seconds. + * @return the current builder for further building. + */ + public Builder gracePeriod(int gp) { + this.gracePeriod = gp; + return this; + } + + /** + * Specify the interval to use. + * @param iv The interval in seconds. + * @return the current builder for further building. + */ + public Builder interval(int iv) { + this.interval = iv; + return this; + } + + /** + * Specify the maximum number of failures. + * @param max The maximum number of failures. + * @return the current builder for further building. + */ + public Builder maxFailures(int max) { + this.maxFailures = max; + return this; + } + + /** + * Specify the timeout. + * @param t The timout in seconds. + * @return the current builder for further building. + */ + public Builder timeout(int t) { + this.timeout = t; + return this; + } + + public HealthCheck build() { + return new HealthCheck(parameters, type, gracePeriod, interval, timeout, maxFailures); + } + } +} http://git-wip-us.apache.org/repos/asf/aries-containers/blob/6289b71d/containers-api/src/main/java/org/apache/aries/containers/ServiceConfig.java ---------------------------------------------------------------------- diff --git a/containers-api/src/main/java/org/apache/aries/containers/ServiceConfig.java b/containers-api/src/main/java/org/apache/aries/containers/ServiceConfig.java index bf48d57..85ca8f0 100644 --- a/containers-api/src/main/java/org/apache/aries/containers/ServiceConfig.java +++ b/containers-api/src/main/java/org/apache/aries/containers/ServiceConfig.java @@ -43,20 +43,21 @@ public class ServiceConfig { private final List<Integer> containerPorts; private final String entryPoint; private final Map<String, String> envVars; -// private final List<HealthCheck> healthChecks; TODO add these! + private final List<HealthCheck> healthChecks; private final double requestedCPUunits; private final int requestedInstances; private final double requestedMemory; // in MiB private final String serviceName; private ServiceConfig(String[] commandLine, String containerImage, List<Integer> containerPorts, String entryPoint, - Map<String, String> envVars, double requestedCPUunits, int requestedInstances, double requestedMemory, - String serviceName) { + Map<String, String> envVars, List<HealthCheck> healtChecks, double requestedCPUunits, int requestedInstances, + double requestedMemory, String serviceName) { this.commandLine = commandLine; this.containerImage = containerImage; this.containerPorts = Collections.unmodifiableList(containerPorts); this.entryPoint = entryPoint; this.envVars = Collections.unmodifiableMap(envVars); + this.healthChecks = Collections.unmodifiableList(healtChecks); this.requestedCPUunits = requestedCPUunits; this.requestedInstances = requestedInstances; this.requestedMemory = requestedMemory; @@ -93,6 +94,13 @@ public class ServiceConfig { } /** + * @return The health checks to be configured for this service. + */ + public List<HealthCheck> getHealthChecks() { + return healthChecks; + } + + /** * @return A map containing all the environment variables to be set. */ public Map<String, String> getEnvVars() { @@ -129,8 +137,6 @@ public class ServiceConfig { return serviceName; } - - @Override public int hashCode() { final int prime = 31; @@ -140,6 +146,7 @@ public class ServiceConfig { result = prime * result + ((containerPorts == null) ? 0 : containerPorts.hashCode()); result = prime * result + ((entryPoint == null) ? 0 : entryPoint.hashCode()); result = prime * result + ((envVars == null) ? 0 : envVars.hashCode()); + result = prime * result + ((healthChecks == null) ? 0 : healthChecks.hashCode()); long temp; temp = Double.doubleToLongBits(requestedCPUunits); result = prime * result + (int) (temp ^ (temp >>> 32)); @@ -181,6 +188,11 @@ public class ServiceConfig { return false; } else if (!envVars.equals(other.envVars)) return false; + if (healthChecks == null) { + if (other.healthChecks != null) + return false; + } else if (!healthChecks.equals(other.healthChecks)) + return false; if (Double.doubleToLongBits(requestedCPUunits) != Double.doubleToLongBits(other.requestedCPUunits)) return false; if (requestedInstances != other.requestedInstances) @@ -210,15 +222,16 @@ public class ServiceConfig { /** A builder for service configurations */ @ProviderType public static class Builder { - private String containerImage; + private final String containerImage; private String[] commandLine = new String [] {}; private Map<String, String> envMap = new HashMap<>(); private String entryPoint; + private List<HealthCheck> healthChecks = new ArrayList<>(); private double requestedCpuUnits = 0.5; private int requestedInstances = 1; private double requestedMemory = 64; private List<Integer> ports = new ArrayList<>(); - private String serviceName; + private final String serviceName; Builder(String serviceName, String containerImage) { this.serviceName = serviceName; @@ -299,6 +312,18 @@ public class ServiceConfig { } /** + * Specify a health check to use for the service. This method + * may be called multiple times to specify multiple health + * checks. + * @param hc The health to add. + * @return the current builder for further building. + */ + public Builder healthCheck(HealthCheck hc) { + this.healthChecks.add(hc); + return this; + } + + /** * Specify the required amount of memory in million bytes (MiB). * * @param requestedMemory The amount of memory required of a container. @@ -328,7 +353,7 @@ public class ServiceConfig { */ public ServiceConfig build() { return new ServiceConfig(commandLine, containerImage, ports, entryPoint, - envMap, requestedCpuUnits, requestedInstances, requestedMemory, + envMap, healthChecks, requestedCpuUnits, requestedInstances, requestedMemory, serviceName); } } http://git-wip-us.apache.org/repos/asf/aries-containers/blob/6289b71d/containers-api/src/test/java/org/apache/aries/containers/api/ServiceConfigTest.java ---------------------------------------------------------------------- diff --git a/containers-api/src/test/java/org/apache/aries/containers/api/ServiceConfigTest.java b/containers-api/src/test/java/org/apache/aries/containers/api/ServiceConfigTest.java index c21519a..934ec4c 100644 --- a/containers-api/src/test/java/org/apache/aries/containers/api/ServiceConfigTest.java +++ b/containers-api/src/test/java/org/apache/aries/containers/api/ServiceConfigTest.java @@ -22,6 +22,7 @@ import java.util.Arrays; import java.util.HashMap; import java.util.Map; +import org.apache.aries.containers.HealthCheck; import org.apache.aries.containers.ServiceConfig; import org.junit.Test; @@ -74,4 +75,14 @@ public class ServiceConfigTest { assertEquals(env, sc.getEnvVars()); } + @Test + public void testHealthCheck() { + HealthCheck hc = HealthCheck.builder(HealthCheck.Type.HTTP). + parameters("/index.html").build(); + ServiceConfig sc = ServiceConfig.builder("mysvc", "animg"). + healthCheck(hc).build(); + + assertEquals(1, sc.getHealthChecks().size()); + assertEquals(hc, sc.getHealthChecks().get(0)); + } }
