| /* |
| * 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 java.util.ArrayList; |
| import java.util.Arrays; |
| import java.util.Collections; |
| import java.util.HashMap; |
| import java.util.List; |
| import java.util.Map; |
| |
| import org.osgi.annotation.versioning.ProviderType; |
| |
| /** |
| * This class defines a service and it's settings. An instance is created via the |
| * {@link Builder} and is immutable. For example to create a service for the Apache |
| * Web Server docker image: |
| * <pre> |
| * ServiceConfig sc = ServiceConfig.builder("myservice", "httpd"). |
| * cpu(0.5).memory(64).port(80).build(); |
| * </pre> |
| */ |
| @ProviderType |
| public class ServiceConfig { |
| private final String[] commandLine; |
| private final String containerImage; |
| 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 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) { |
| this.commandLine = commandLine; |
| this.containerImage = containerImage; |
| this.containerPorts = Collections.unmodifiableList(containerPorts); |
| this.entryPoint = entryPoint; |
| this.envVars = Collections.unmodifiableMap(envVars); |
| this.requestedCPUunits = requestedCPUunits; |
| this.requestedInstances = requestedInstances; |
| this.requestedMemory = requestedMemory; |
| this.serviceName = serviceName; |
| } |
| |
| /** |
| * @return The command line to be used by the container. See also {@link #getEntryPoint()}. |
| */ |
| public String[] getCommandLine() { |
| return commandLine.clone(); |
| } |
| |
| /** |
| * @return The name of the container image. |
| */ |
| public String getContainerImage() { |
| return containerImage; |
| } |
| |
| /** |
| * @return A list of the ports exposed externally. |
| */ |
| public List<Integer> getContainerPorts() { |
| return containerPorts; |
| } |
| |
| /** |
| * @return The entry point to be used with the image. Together with the {@link #getCommandLine()} |
| * this defines the process run in the image. |
| */ |
| public String getEntryPoint() { |
| return entryPoint; |
| } |
| |
| /** |
| * @return A map containing all the environment variables to be set. |
| */ |
| public Map<String, String> getEnvVars() { |
| return envVars; |
| } |
| |
| /** |
| * @return The cpu units required for each container running this service. |
| */ |
| public double getRequestedCpuUnits() { |
| return requestedCPUunits; |
| } |
| |
| /** |
| * @return The number of replica containers requested for the service. |
| */ |
| public int getRequestedInstances() { |
| return requestedInstances; |
| } |
| |
| /** |
| * @return The amount of memory require for each container running the service. |
| * Specified in million bytes (MiB). |
| */ |
| public double getRequestedMemory() { |
| return requestedMemory; |
| } |
| |
| /** |
| * The name of the service deployment. This has to be unique in the system. |
| * @return The name of the service. |
| */ |
| public String getServiceName() { |
| return serviceName; |
| } |
| |
| |
| |
| @Override |
| public int hashCode() { |
| final int prime = 31; |
| int result = 1; |
| result = prime * result + Arrays.hashCode(commandLine); |
| result = prime * result + ((containerImage == null) ? 0 : containerImage.hashCode()); |
| result = prime * result + ((containerPorts == null) ? 0 : containerPorts.hashCode()); |
| result = prime * result + ((entryPoint == null) ? 0 : entryPoint.hashCode()); |
| result = prime * result + ((envVars == null) ? 0 : envVars.hashCode()); |
| long temp; |
| temp = Double.doubleToLongBits(requestedCPUunits); |
| result = prime * result + (int) (temp ^ (temp >>> 32)); |
| result = prime * result + requestedInstances; |
| temp = Double.doubleToLongBits(requestedMemory); |
| result = prime * result + (int) (temp ^ (temp >>> 32)); |
| result = prime * result + ((serviceName == null) ? 0 : serviceName.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; |
| ServiceConfig other = (ServiceConfig) obj; |
| if (!Arrays.equals(commandLine, other.commandLine)) |
| return false; |
| if (containerImage == null) { |
| if (other.containerImage != null) |
| return false; |
| } else if (!containerImage.equals(other.containerImage)) |
| return false; |
| if (containerPorts == null) { |
| if (other.containerPorts != null) |
| return false; |
| } else if (!containerPorts.equals(other.containerPorts)) |
| return false; |
| if (entryPoint == null) { |
| if (other.entryPoint != null) |
| return false; |
| } else if (!entryPoint.equals(other.entryPoint)) |
| return false; |
| if (envVars == null) { |
| if (other.envVars != null) |
| return false; |
| } else if (!envVars.equals(other.envVars)) |
| return false; |
| if (Double.doubleToLongBits(requestedCPUunits) != Double.doubleToLongBits(other.requestedCPUunits)) |
| return false; |
| if (requestedInstances != other.requestedInstances) |
| return false; |
| if (Double.doubleToLongBits(requestedMemory) != Double.doubleToLongBits(other.requestedMemory)) |
| return false; |
| if (serviceName == null) { |
| if (other.serviceName != null) |
| return false; |
| } else if (!serviceName.equals(other.serviceName)) |
| return false; |
| return true; |
| } |
| |
| /** |
| * Obtain a service configuration builder. |
| * @param serviceName The name for the service. This name should be unique in the |
| * deployment, should be alphanum only and should not exceed 32 characters. |
| * @param containerImage The container image to use. When using docker, this is |
| * the docker image that should be used. |
| * @return A service configuration builder |
| */ |
| public static Builder builder(String serviceName, String containerImage) { |
| return new Builder(serviceName, containerImage); |
| } |
| |
| /** A builder for service configurations */ |
| @ProviderType |
| public static class Builder { |
| private String containerImage; |
| private String[] commandLine = new String [] {}; |
| private Map<String, String> envMap = new HashMap<>(); |
| private String entryPoint; |
| private double requestedCpuUnits = 0.5; |
| private int requestedInstances = 1; |
| private double requestedMemory = 64; |
| private List<Integer> ports = new ArrayList<>(); |
| private String serviceName; |
| |
| Builder(String serviceName, String containerImage) { |
| this.serviceName = serviceName; |
| this.containerImage = containerImage; |
| } |
| |
| /** The command line for the service. Also note that some images may need |
| * an {@link #entryPoint(String)} specified in order to change behaviour. |
| * |
| * @param commandLine The command line to use. |
| * @return the current builder for further building. |
| */ |
| public Builder commandLine(String ... commandLine) { |
| this.commandLine = commandLine; |
| return this; |
| } |
| |
| /** |
| * The requested CPU for the service. |
| * |
| * @param requestedCpuUnits The requested CPU in CPU fractional units. |
| * @return the current builder for further building. |
| */ |
| public Builder cpu(double requestedCpuUnits) { |
| this.requestedCpuUnits = requestedCpuUnits; |
| return this; |
| } |
| |
| /** |
| * The entrypoint to use. Effectively the entrypoint together with the |
| * commandline defines the process launched by the container. |
| * |
| * @param entryPoint The entry point to use. |
| * @return the current builder for further building. |
| */ |
| public Builder entryPoint(String entryPoint) { |
| this.entryPoint = entryPoint; |
| return this; |
| } |
| |
| /** |
| * Specify an environment variable. The variable is added to previously |
| * specified environment variables and this builder method can be called |
| * multiple times. |
| * |
| * @param name The variable name. |
| * @param value The variable value. |
| * @return the current builder for further building. |
| */ |
| public Builder env(String name, String value) { |
| this.envMap.put(name, value); |
| return this; |
| } |
| |
| /** |
| * Set the environment variables to the provided map. This will replace |
| * any previously specified environment variables. |
| * |
| * @param envMap The map of environment variables. |
| * @return the current builder for further building. |
| */ |
| public Builder env(Map<String, String> envMap) { |
| this.envMap.clear(); |
| this.envMap.putAll(envMap); |
| return this; |
| } |
| |
| /** |
| * Specify the number of container instances required for this service. |
| * The container will be deployed as many times as specified here. |
| * |
| * @param requestedInstances The number of required instances. |
| * @return the current builder for further building. |
| */ |
| public Builder instances(int requestedInstances) { |
| this.requestedInstances = requestedInstances; |
| return this; |
| } |
| |
| /** |
| * Specify the required amount of memory in million bytes (MiB). |
| * |
| * @param requestedMemory The amount of memory required of a container. |
| * @return the current builder for further building. |
| */ |
| public Builder memory(double requestedMemory) { |
| this.requestedMemory = requestedMemory; |
| return this; |
| } |
| |
| /** |
| * Specify an external port to be exposed by the container. When a container |
| * exposes multiple ports, call this builder method multiple times. |
| * |
| * @param port The port to be exposed externally. |
| * @return the current builder for further building. |
| */ |
| public Builder port(int port) { |
| this.ports.add(port); |
| return this; |
| } |
| |
| /** |
| * Build the configuration from the information gathered in the builder. |
| * |
| * @return An immutable service configuration. |
| */ |
| public ServiceConfig build() { |
| return new ServiceConfig(commandLine, containerImage, ports, entryPoint, |
| envMap, requestedCpuUnits, requestedInstances, requestedMemory, |
| serviceName); |
| } |
| } |
| } |