You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@brooklyn.apache.org by dr...@apache.org on 2017/06/29 15:36:05 UTC
[23/50] [abbrv] brooklyn-server git commit: no_entry: Move kubernetes
classes to new location
http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/445884b1/kubernetes-location/src/main/java/io/cloudsoft/amp/containerservice/kubernetes/location/KubernetesLocation.java
----------------------------------------------------------------------
diff --git a/kubernetes-location/src/main/java/io/cloudsoft/amp/containerservice/kubernetes/location/KubernetesLocation.java b/kubernetes-location/src/main/java/io/cloudsoft/amp/containerservice/kubernetes/location/KubernetesLocation.java
deleted file mode 100644
index e87866c..0000000
--- a/kubernetes-location/src/main/java/io/cloudsoft/amp/containerservice/kubernetes/location/KubernetesLocation.java
+++ /dev/null
@@ -1,1014 +0,0 @@
-package io.cloudsoft.amp.containerservice.kubernetes.location;
-
-import java.io.InputStream;
-import java.net.InetAddress;
-import java.nio.charset.Charset;
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import java.util.concurrent.Callable;
-import java.util.concurrent.TimeUnit;
-
-import org.apache.brooklyn.api.entity.Entity;
-import org.apache.brooklyn.api.location.LocationSpec;
-import org.apache.brooklyn.api.location.MachineLocation;
-import org.apache.brooklyn.api.location.MachineProvisioningLocation;
-import org.apache.brooklyn.api.location.NoMachinesAvailableException;
-import org.apache.brooklyn.api.location.PortRange;
-import org.apache.brooklyn.api.sensor.AttributeSensor;
-import org.apache.brooklyn.api.sensor.EnricherSpec;
-import org.apache.brooklyn.config.ConfigKey;
-import org.apache.brooklyn.core.entity.BrooklynConfigKeys;
-import org.apache.brooklyn.core.entity.EntityInternal;
-import org.apache.brooklyn.core.location.AbstractLocation;
-import org.apache.brooklyn.core.location.LocationConfigKeys;
-import org.apache.brooklyn.core.location.PortRanges;
-import org.apache.brooklyn.core.location.access.PortForwardManager;
-import org.apache.brooklyn.core.location.access.PortForwardManagerLocationResolver;
-import org.apache.brooklyn.core.location.cloud.CloudLocationConfig;
-import org.apache.brooklyn.core.network.OnPublicNetworkEnricher;
-import org.apache.brooklyn.core.sensor.Sensors;
-import org.apache.brooklyn.location.ssh.SshMachineLocation;
-import org.apache.brooklyn.util.collections.MutableList;
-import org.apache.brooklyn.util.collections.MutableMap;
-import org.apache.brooklyn.util.core.ResourceUtils;
-import org.apache.brooklyn.util.core.config.ConfigBag;
-import org.apache.brooklyn.util.core.config.ResolvingConfigBag;
-import org.apache.brooklyn.util.core.internal.ssh.SshTool;
-import org.apache.brooklyn.util.core.text.TemplateProcessor;
-import org.apache.brooklyn.util.exceptions.ReferenceWithError;
-import org.apache.brooklyn.util.net.Networking;
-import org.apache.brooklyn.util.repeat.Repeater;
-import org.apache.brooklyn.util.stream.Streams;
-import org.apache.brooklyn.util.text.Identifiers;
-import org.apache.brooklyn.util.text.Strings;
-import org.apache.brooklyn.util.time.Duration;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import com.google.common.base.Functions;
-import com.google.common.base.Joiner;
-import com.google.common.base.Optional;
-import com.google.common.base.Predicate;
-import com.google.common.base.Predicates;
-import com.google.common.base.Stopwatch;
-import com.google.common.base.Throwables;
-import com.google.common.collect.ImmutableList;
-import com.google.common.collect.ImmutableMap;
-import com.google.common.collect.ImmutableSet;
-import com.google.common.collect.Iterables;
-import com.google.common.collect.Lists;
-import com.google.common.collect.Maps;
-import com.google.common.collect.Sets;
-import com.google.common.io.BaseEncoding;
-import com.google.common.net.HostAndPort;
-
-import io.cloudsoft.amp.containerservice.dockercontainer.DockerContainer;
-import io.cloudsoft.amp.containerservice.dockerlocation.DockerJcloudsLocation;
-import io.cloudsoft.amp.containerservice.kubernetes.entity.KubernetesPod;
-import io.cloudsoft.amp.containerservice.kubernetes.entity.KubernetesResource;
-import io.cloudsoft.amp.containerservice.kubernetes.location.machine.KubernetesEmptyMachineLocation;
-import io.cloudsoft.amp.containerservice.kubernetes.location.machine.KubernetesMachineLocation;
-import io.cloudsoft.amp.containerservice.kubernetes.location.machine.KubernetesSshMachineLocation;
-import io.fabric8.kubernetes.api.model.Container;
-import io.fabric8.kubernetes.api.model.ContainerBuilder;
-import io.fabric8.kubernetes.api.model.ContainerPort;
-import io.fabric8.kubernetes.api.model.ContainerPortBuilder;
-import io.fabric8.kubernetes.api.model.EndpointAddress;
-import io.fabric8.kubernetes.api.model.EndpointSubset;
-import io.fabric8.kubernetes.api.model.Endpoints;
-import io.fabric8.kubernetes.api.model.EnvVar;
-import io.fabric8.kubernetes.api.model.EnvVarBuilder;
-import io.fabric8.kubernetes.api.model.HasMetadata;
-import io.fabric8.kubernetes.api.model.Namespace;
-import io.fabric8.kubernetes.api.model.NamespaceBuilder;
-import io.fabric8.kubernetes.api.model.PersistentVolume;
-import io.fabric8.kubernetes.api.model.PersistentVolumeBuilder;
-import io.fabric8.kubernetes.api.model.Pod;
-import io.fabric8.kubernetes.api.model.PodList;
-import io.fabric8.kubernetes.api.model.PodTemplateSpec;
-import io.fabric8.kubernetes.api.model.PodTemplateSpecBuilder;
-import io.fabric8.kubernetes.api.model.QuantityBuilder;
-import io.fabric8.kubernetes.api.model.ReplicationController;
-import io.fabric8.kubernetes.api.model.ResourceRequirements;
-import io.fabric8.kubernetes.api.model.ResourceRequirementsBuilder;
-import io.fabric8.kubernetes.api.model.Secret;
-import io.fabric8.kubernetes.api.model.SecretBuilder;
-import io.fabric8.kubernetes.api.model.Service;
-import io.fabric8.kubernetes.api.model.ServiceBuilder;
-import io.fabric8.kubernetes.api.model.ServicePort;
-import io.fabric8.kubernetes.api.model.ServicePortBuilder;
-import io.fabric8.kubernetes.api.model.extensions.Deployment;
-import io.fabric8.kubernetes.api.model.extensions.DeploymentBuilder;
-import io.fabric8.kubernetes.api.model.extensions.DeploymentStatus;
-import io.fabric8.kubernetes.client.KubernetesClient;
-import io.fabric8.kubernetes.client.KubernetesClientException;
-
-public class KubernetesLocation extends AbstractLocation implements MachineProvisioningLocation<KubernetesMachineLocation>, KubernetesLocationConfig {
-
- /*
- * TODO
- *
- * - Ignores config such as 'user' and 'password', just uses 'loginUser'
- * and 'loginUser.password' for connecting to the container.
- * - Does not create a user, so behaves differently from things that use
- * JcloudsLocation.
- * - Does not use ssh keys only passwords.
- * - The 'cloudsoft/*' images use root which is discouraged.
- * - Error handling needs revisited. For example, if provisioning fails then
- * it waits for five minutes and then fails without a reason why.
- * e.g. try launching a container with an incorrect image name.
- */
-
- private static final Logger LOG = LoggerFactory.getLogger(KubernetesLocation.class);
-
- public static final String NODE_PORT = "NodePort";
-
- public static final String IMMUTABLE_CONTAINER_KEY = "immutable-container";
- public static final String SSHABLE_CONTAINER = "sshable-container";
- public static final String CLOUDSOFT_ENTITY_ID = "cloudsoft.io/entity-id";
- public static final String CLOUDSOFT_APPLICATION_ID = "cloudsoft.io/application-id";
- public static final String KUBERNETES_DOCKERCFG = "kubernetes.io/dockercfg";
-
- public static final String PHASE_AVAILABLE = "Available";
- public static final String PHASE_TERMINATING = "Terminating";
- public static final String PHASE_ACTIVE = "Active";
-
- /**
- * The regex for the image descriptions that support us injecting login credentials.
- */
- public static final List<String> IMAGE_DESCRIPTION_REGEXES_REQUIRING_INJECTED_LOGIN_CREDS = ImmutableList.of(
- "cloudsoft/centos.*",
- "cloudsoft/ubuntu.*");
-
- /** The environment variable for injecting login credentials. */
- public static final String CLOUDSOFT_ROOT_PASSWORD = "CLOUDSOFT_ROOT_PASSWORD";
-
- private KubernetesClient client;
-
- public KubernetesLocation() {
- super();
- }
-
- public KubernetesLocation(Map<?, ?> properties) {
- super(properties);
- }
-
- @Override
- public void init() {
- super.init();
- }
-
- protected KubernetesClient getClient() {
- return getClient(MutableMap.of());
- }
-
- protected KubernetesClient getClient(Map<?, ?> flags) {
- ConfigBag conf = (flags == null || flags.isEmpty())
- ? config().getBag()
- : ConfigBag.newInstanceExtending(config().getBag(), flags);
- return getClient(conf);
- }
-
- protected KubernetesClient getClient(ConfigBag config) {
- if (client == null) {
- KubernetesClientRegistry registry = getConfig(KUBERNETES_CLIENT_REGISTRY);
- client = registry.getKubernetesClient(ResolvingConfigBag.newInstanceExtending(getManagementContext(), config));
- }
- return client;
- }
-
- @Override
- public KubernetesMachineLocation obtain(Map<?, ?> flags) throws NoMachinesAvailableException {
- ConfigBag setupRaw = ConfigBag.newInstanceExtending(config().getBag(), flags);
- ConfigBag setup = ResolvingConfigBag.newInstanceExtending(getManagementContext(), setupRaw);
-
- client = getClient(setup);
- Entity entity = validateCallerContext(setup);
- if (isKubernetesResource(entity)) {
- return createKubernetesResourceLocation(entity, setup);
- } else {
- return createKubernetesContainerLocation(entity, setup);
- }
- }
-
- @Override
- public void release(KubernetesMachineLocation machine) {
- Entity entity = validateCallerContext(machine);
- if (isKubernetesResource(entity)) {
- deleteKubernetesResourceLocation(entity);
- } else {
- deleteKubernetesContainerLocation(entity, machine);
- }
- }
-
- protected void deleteKubernetesContainerLocation(Entity entity, MachineLocation machine) {
- final String namespace = entity.sensors().get(KubernetesPod.KUBERNETES_NAMESPACE);
- final String deployment = entity.sensors().get(KubernetesPod.KUBERNETES_DEPLOYMENT);
- final String pod = entity.sensors().get(KubernetesPod.KUBERNETES_POD);
- final String service = entity.sensors().get(KubernetesPod.KUBERNETES_SERVICE);
-
- undeploy(namespace, deployment, pod);
-
- client.services().inNamespace(namespace).withName(service).delete();
- ExitCondition exitCondition = new ExitCondition() {
- @Override
- public Boolean call() {
- return client.services().inNamespace(namespace).withName(service).get() == null;
- }
- @Override
- public String getFailureMessage() {
- return "No service with namespace=" + namespace + ", serviceName=" + service;
- }
- };
- waitForExitCondition(exitCondition);
-
- Boolean delete = machine.config().get(DELETE_EMPTY_NAMESPACE);
- if (delete) {
- deleteEmptyNamespace(namespace);
- }
- }
-
- protected void deleteKubernetesResourceLocation(Entity entity) {
- final String namespace = entity.sensors().get(KubernetesPod.KUBERNETES_NAMESPACE);
- final String resourceType = entity.sensors().get(KubernetesResource.RESOURCE_TYPE);
- final String resourceName = entity.sensors().get(KubernetesResource.RESOURCE_NAME);
-
- if (!handleResourceDelete(resourceType, resourceName, namespace)) {
- LOG.warn("Resource {}: {} not deleted", resourceName, resourceType);
- }
- }
-
- protected boolean handleResourceDelete(String resourceType, String resourceName, String namespace) {
- try {
- switch (resourceType) {
- case KubernetesResource.DEPLOYMENT:
- return client.extensions().deployments().inNamespace(namespace).withName(resourceName).delete();
- case KubernetesResource.REPLICA_SET:
- return client.extensions().replicaSets().inNamespace(namespace).withName(resourceName).delete();
- case KubernetesResource.CONFIG_MAP:
- return client.configMaps().inNamespace(namespace).withName(resourceName).delete();
- case KubernetesResource.PERSISTENT_VOLUME:
- return client.persistentVolumes().withName(resourceName).delete();
- case KubernetesResource.SECRET:
- return client.secrets().inNamespace(namespace).withName(resourceName).delete();
- case KubernetesResource.SERVICE:
- return client.services().inNamespace(namespace).withName(resourceName).delete();
- case KubernetesResource.REPLICATION_CONTROLLER:
- return client.replicationControllers().inNamespace(namespace).withName(resourceName).delete();
- case KubernetesResource.NAMESPACE:
- return client.namespaces().withName(resourceName).delete();
- }
- } catch (KubernetesClientException kce) {
- LOG.warn("Error deleting resource {}: {}", resourceName, kce);
- }
- return false;
- }
-
- protected void undeploy(final String namespace, final String deployment, final String pod) {
- client.extensions().deployments().inNamespace(namespace).withName(deployment).delete();
- ExitCondition exitCondition = new ExitCondition() {
- @Override
- public Boolean call() {
- return client.extensions().deployments().inNamespace(namespace).withName(deployment).get() == null;
- }
- @Override
- public String getFailureMessage() {
- return "No deployment with namespace=" + namespace + ", deployment=" + deployment;
- }
- };
- waitForExitCondition(exitCondition);
- }
-
- protected synchronized void deleteEmptyNamespace(final String name) {
- if (!name.equals("default") && isNamespaceEmpty(name)) {
- if (client.namespaces().withName(name).get() != null &&
- !client.namespaces().withName(name).get().getStatus().getPhase().equals(PHASE_TERMINATING)) {
- client.namespaces().withName(name).delete();
- ExitCondition exitCondition = new ExitCondition() {
- @Override
- public Boolean call() {
- return client.namespaces().withName(name).get() == null;
- }
- @Override
- public String getFailureMessage() {
- return "Namespace " + name + " still present";
- }
- };
- waitForExitCondition(exitCondition);
- }
- }
- }
-
- protected boolean isNamespaceEmpty(String name) {
- return client.extensions().deployments().inNamespace(name).list().getItems().isEmpty() &&
- client.services().inNamespace(name).list().getItems().isEmpty() &&
- client.secrets().inNamespace(name).list().getItems().isEmpty();
- }
-
- @Override
- public Map<String, Object> getProvisioningFlags(Collection<String> tags) {
- return null;
- }
-
- protected KubernetesMachineLocation createKubernetesResourceLocation(Entity entity, ConfigBag setup) {
- String resourceUri = entity.config().get(KubernetesResource.RESOURCE_FILE);
- InputStream resource = ResourceUtils.create(entity).getResourceFromUrl(resourceUri);
- String templateContents = Streams.readFullyString(resource);
- String processedContents = TemplateProcessor.processTemplateContents(templateContents, (EntityInternal) entity, setup.getAllConfig());
- InputStream processedResource = Streams.newInputStreamWithContents(processedContents);
-
- final List<HasMetadata> result = getClient().load(processedResource).createOrReplace();
-
- ExitCondition exitCondition = new ExitCondition() {
- @Override
- public Boolean call() {
- if (result.isEmpty()) {
- return false;
- }
- List<HasMetadata> check = client.resource(result.get(0)).inNamespace(result.get(0).getMetadata().getNamespace()).get();
- if (result.size() > 1 || check.size() != 1 || check.get(0).getMetadata() == null) {
- return false;
- }
- return true;
- }
- @Override
- public String getFailureMessage() {
- return "Cannot find created resources";
- }
- };
- waitForExitCondition(exitCondition);
-
- HasMetadata metadata = result.get(0);
- String resourceType = metadata.getKind();
- String resourceName = metadata.getMetadata().getName();
- String namespace = metadata.getMetadata().getNamespace();
- LOG.debug("Resource {} (type {}) deployed to {}", resourceName, resourceType, namespace);
-
- entity.sensors().set(KubernetesPod.KUBERNETES_NAMESPACE, namespace);
- entity.sensors().set(KubernetesResource.RESOURCE_NAME, resourceName);
- entity.sensors().set(KubernetesResource.RESOURCE_TYPE, resourceType);
-
- LocationSpec<? extends KubernetesMachineLocation> locationSpec = LocationSpec.create(KubernetesSshMachineLocation.class);
- if (!findResourceAddress(locationSpec, entity, metadata, resourceType, resourceName, namespace)) {
- LOG.info("Resource {} with type {} has no associated address", resourceName, resourceType);
- locationSpec = LocationSpec.create(KubernetesEmptyMachineLocation.class);
- }
- locationSpec.configure(CALLER_CONTEXT, setup.get(CALLER_CONTEXT))
- .configure(KubernetesMachineLocation.KUBERNETES_NAMESPACE, namespace)
- .configure(KubernetesMachineLocation.KUBERNETES_RESOURCE_NAME, resourceName)
- .configure(KubernetesMachineLocation.KUBERNETES_RESOURCE_TYPE, resourceType);
-
- KubernetesMachineLocation machine = getManagementContext().getLocationManager().createLocation(locationSpec);
-
- if (resourceType.equals(KubernetesResource.SERVICE) && machine instanceof KubernetesSshMachineLocation) {
- Service service = getService(namespace, resourceName);
- registerPortMappings((KubernetesSshMachineLocation) machine, entity, service);
- }
-
- return machine;
- }
-
- protected boolean findResourceAddress(LocationSpec<? extends KubernetesMachineLocation> locationSpec, Entity entity, HasMetadata metadata, String resourceType, String resourceName, String namespace) {
- if (resourceType.equals(KubernetesResource.DEPLOYMENT) || resourceType.equals(KubernetesResource.REPLICATION_CONTROLLER) || resourceType.equals(KubernetesResource.POD)) {
- Map<String, String> labels = MutableMap.of();
- if (resourceType.equals(KubernetesResource.DEPLOYMENT)) {
- Deployment deployment = (Deployment) metadata;
- labels = deployment.getSpec().getTemplate().getMetadata().getLabels();
- } else if (resourceType.equals(KubernetesResource.REPLICATION_CONTROLLER)) {
- ReplicationController replicationController = (ReplicationController) metadata;
- labels = replicationController.getSpec().getTemplate().getMetadata().getLabels();
- }
- Pod pod = resourceType.equals(KubernetesResource.POD) ? getPod(namespace, resourceName) : getPod(namespace, labels);
- entity.sensors().set(KubernetesPod.KUBERNETES_POD, pod.getMetadata().getName());
-
- InetAddress node = Networking.getInetAddressWithFixedName(pod.getSpec().getNodeName());
- String podAddress = pod.getStatus().getPodIP();
-
- locationSpec.configure("address", node);
- locationSpec.configure(SshMachineLocation.PRIVATE_ADDRESSES, ImmutableSet.of(podAddress));
-
- return true;
- } else if (resourceType.equals(KubernetesResource.SERVICE)) {
- getService(namespace, resourceName);
- Endpoints endpoints = client.endpoints().inNamespace(namespace).withName(resourceName).get();
- Set<String> privateIps = Sets.newLinkedHashSet();
- Set<String> podNames = Sets.newLinkedHashSet();
- for (EndpointSubset subset : endpoints.getSubsets()) {
- for (EndpointAddress address : subset.getAddresses()) {
- String podName = address.getTargetRef().getName();
- podNames.add(podName);
- String privateIp = address.getIp();
- privateIps.add(privateIp);
- }
- }
- locationSpec.configure(SshMachineLocation.PRIVATE_ADDRESSES, ImmutableSet.copyOf(privateIps));
-
- if (podNames.size() > 0) {
- // Use the first pod name from the list; warn when multiple pods are referenced
- String podName = Iterables.get(podNames, 0);
- if (podNames.size() > 1) {
- LOG.warn("Multiple pods referenced by service {} in namespace {}, using {}: {}",
- new Object[] { resourceName, namespace, podName, Iterables.toString(podNames) });
- }
- try {
- Pod pod = getPod(namespace, podName);
- entity.sensors().set(KubernetesPod.KUBERNETES_POD, podName);
-
- InetAddress node = Networking.getInetAddressWithFixedName(pod.getSpec().getNodeName());
- locationSpec.configure("address", node);
- } catch (KubernetesClientException kce) {
- LOG.warn("Cannot find pod {} in namespace {} for service {}", new Object[] { podName, namespace, resourceName });
- }
- }
-
- return true;
- } else {
- return false;
- }
- }
-
- protected KubernetesMachineLocation createKubernetesContainerLocation(Entity entity, ConfigBag setup) {
- String deploymentName = lookup(KubernetesPod.DEPLOYMENT, entity, setup, entity.getId());
- Integer replicas = lookup(KubernetesPod.REPLICAS, entity, setup);
- List<String> volumes = lookup(KubernetesPod.PERSISTENT_VOLUMES, entity, setup);
- Map<String, String> secrets = lookup(KubernetesPod.SECRETS, entity, setup);
- Map<String, String> limits = lookup(KubernetesPod.LIMITS, entity, setup);
- Boolean privileged = lookup(KubernetesPod.PRIVILEGED, entity, setup);
- String imageName = findImageName(entity, setup);
- Iterable<Integer> inboundPorts = findInboundPorts(entity, setup);
- Map<String, String> env = findEnvironmentVariables(entity, setup, imageName);
- Map<String, String> metadata = findMetadata(entity, setup, deploymentName);
-
- if (volumes != null) {
- createPersistentVolumes(volumes);
- }
-
- Namespace namespace = createOrGetNamespace(lookup(NAMESPACE, entity, setup), setup.get(CREATE_NAMESPACE));
-
- if (secrets != null) {
- createSecrets(namespace.getMetadata().getName(), secrets);
- }
-
- Container container = buildContainer(namespace.getMetadata().getName(), metadata, deploymentName, imageName, inboundPorts, env, limits, privileged);
- deploy(namespace.getMetadata().getName(), entity, metadata, deploymentName, container, replicas, secrets);
- Service service = exposeService(namespace.getMetadata().getName(), metadata, deploymentName, inboundPorts);
- Pod pod = getPod(namespace.getMetadata().getName(), metadata);
-
- entity.sensors().set(KubernetesPod.KUBERNETES_NAMESPACE, namespace.getMetadata().getName());
- entity.sensors().set(KubernetesPod.KUBERNETES_DEPLOYMENT, deploymentName);
- entity.sensors().set(KubernetesPod.KUBERNETES_POD, pod.getMetadata().getName());
- entity.sensors().set(KubernetesPod.KUBERNETES_SERVICE, service.getMetadata().getName());
-
- LocationSpec<KubernetesSshMachineLocation> locationSpec = prepareSshableLocationSpec(entity, setup, namespace, deploymentName, service, pod)
- .configure(KubernetesMachineLocation.KUBERNETES_NAMESPACE, namespace.getMetadata().getName())
- .configure(KubernetesMachineLocation.KUBERNETES_RESOURCE_NAME, deploymentName)
- .configure(KubernetesMachineLocation.KUBERNETES_RESOURCE_TYPE, getContainerResourceType());
-
- KubernetesSshMachineLocation machine = getManagementContext().getLocationManager().createLocation(locationSpec);
- registerPortMappings(machine, entity, service);
- if (!isDockerContainer(entity)) {
- waitForSshable(machine, Duration.FIVE_MINUTES);
- }
-
- return machine;
- }
-
- protected String getContainerResourceType() {
- return KubernetesResource.DEPLOYMENT;
- }
-
- protected void waitForSshable(final SshMachineLocation machine, Duration timeout) {
- Callable<Boolean> checker = new Callable<Boolean>() {
- public Boolean call() {
- int exitstatus = machine.execScript(
- ImmutableMap.of( // TODO investigate why SSH connection does not time out with this config
- SshTool.PROP_CONNECT_TIMEOUT.getName(), Duration.TEN_SECONDS.toMilliseconds(),
- SshTool.PROP_SESSION_TIMEOUT.getName(), Duration.TEN_SECONDS.toMilliseconds(),
- SshTool.PROP_SSH_TRIES_TIMEOUT.getName(), Duration.TEN_SECONDS.toMilliseconds(),
- SshTool.PROP_SSH_TRIES.getName(), 1),
- "check-sshable",
- ImmutableList.of("true"));
- boolean success = (exitstatus == 0);
- return success;
- }};
-
- Stopwatch stopwatch = Stopwatch.createStarted();
- ReferenceWithError<Boolean> reachable = Repeater.create("reachable")
- .threaded()
- .backoff(Duration.FIVE_SECONDS, 2, Duration.TEN_SECONDS) // Exponential backoff, to 10 seconds
- .until(checker)
- .limitTimeTo(timeout)
- .runKeepingError();
- if (!reachable.getWithoutError()) {
- throw new IllegalStateException("Connection failed for "+machine.getSshHostAndPort()+" after waiting "+stopwatch.elapsed(TimeUnit.SECONDS), reachable.getError());
- } else {
- LOG.debug("Connection succeeded for {} after {}", machine.getSshHostAndPort(), stopwatch.elapsed(TimeUnit.SECONDS));
- }
- }
-
- protected void registerPortMappings(KubernetesSshMachineLocation machine, Entity entity, Service service) {
- PortForwardManager portForwardManager = (PortForwardManager) getManagementContext().getLocationRegistry()
- .getLocationManaged(PortForwardManagerLocationResolver.PFM_GLOBAL_SPEC);
- List<ServicePort> ports = service.getSpec().getPorts();
- String publicHostText = ((SshMachineLocation) machine).getSshHostAndPort().getHostText();
- LOG.debug("Recording port-mappings for container {} of {}: {}", new Object[] { machine, this, ports });
-
- for (ServicePort port : ports) {
- String protocol = port.getProtocol();
- Integer targetPort = port.getTargetPort().getIntVal();
-
- if (!"TCP".equalsIgnoreCase(protocol)) {
- LOG.debug("Ignoring port mapping {} for {} because only TCP is currently supported", port, machine);
- } else if (targetPort == null) {
- LOG.debug("Ignoring port mapping {} for {} because targetPort.intValue is null", port, machine);
- } else if (port.getNodePort() == null) {
- LOG.debug("Ignoring port mapping {} to {} because port.getNodePort() is null", targetPort, machine);
- } else {
- portForwardManager.associate(publicHostText, HostAndPort.fromParts(publicHostText, port.getNodePort()), machine, targetPort);
- AttributeSensor<Integer> sensor = Sensors.newIntegerSensor("kubernetes." + Strings.maybeNonBlank(port.getName()).or(targetPort.toString()) + ".port");
- entity.sensors().set(sensor, targetPort);
- }
- }
-
- entity.enrichers().add(EnricherSpec.create(OnPublicNetworkEnricher.class).configure(OnPublicNetworkEnricher.MAP_MATCHING, "kubernetes.[a-zA-Z0-9][a-zA-Z0-9-_]*.port"));
- }
-
- protected synchronized Namespace createOrGetNamespace(final String name, Boolean create) {
- Namespace namespace = client.namespaces().withName(name).get();
- ExitCondition namespaceReady = new ExitCondition() {
- @Override
- public Boolean call() {
- Namespace actualNamespace = client.namespaces().withName(name).get();
- return actualNamespace != null && actualNamespace.getStatus().getPhase().equals(PHASE_ACTIVE);
- }
- @Override
- public String getFailureMessage() {
- Namespace actualNamespace = client.namespaces().withName(name).get();
- return "Namespace for " + name + " " + (actualNamespace == null ? "absent" : " status " + actualNamespace.getStatus());
- }
- };
- if (namespace != null) {
- LOG.debug("Found namespace {}, returning it.", namespace);
- } else if (create) {
- namespace = client.namespaces().create(new NamespaceBuilder().withNewMetadata().withName(name).endMetadata().build());
- LOG.debug("Created namespace {}.", namespace);
- } else {
- throw new IllegalStateException("Namespace " + name + " does not exist and namespace.create is not set");
- }
- waitForExitCondition(namespaceReady);
- return client.namespaces().withName(name).get();
- }
-
- protected Pod getPod(final String namespace, final String name) {
- ExitCondition exitCondition = new ExitCondition() {
- @Override
- public Boolean call() {
- Pod result = client.pods().inNamespace(namespace).withName(name).get();
- return result != null && result.getStatus().getPodIP() != null;
- }
- @Override
- public String getFailureMessage() {
- return "Cannot find pod with name: " + name;
- }
- };
- waitForExitCondition(exitCondition);
- Pod result = client.pods().inNamespace(namespace).withName(name).get();
- return result;
- }
-
- protected Pod getPod(final String namespace, final Map<String, String> metadata) {
- ExitCondition exitCondition = new ExitCondition() {
- @Override
- public Boolean call() {
- PodList result = client.pods().inNamespace(namespace).withLabels(metadata).list();
- return result.getItems().size() >= 1 && result.getItems().get(0).getStatus().getPodIP() != null;
- }
- @Override
- public String getFailureMessage() {
- return "Cannot find pod with metadata: " + Joiner.on(" ").withKeyValueSeparator("=").join(metadata);
- }
- };
- waitForExitCondition(exitCondition);
- PodList result = client.pods().inNamespace(namespace).withLabels(metadata).list();
- return result.getItems().get(0);
- }
-
- protected void createSecrets(String namespace, Map<String, String> secrets) {
- for (Map.Entry<String, String> nameAuthEntry : secrets.entrySet()) {
- createSecret(namespace, nameAuthEntry.getKey(), nameAuthEntry.getValue());
- }
- }
-
- protected Secret createSecret(final String namespace, final String secretName, String auth) {
- Secret secret = client.secrets().inNamespace(namespace).withName(secretName).get();
- if (secret != null) return secret;
-
- String json = String.format("{\"https://index.docker.io/v1/\":{\"auth\":\"%s\"}}", auth);
- String base64encoded = BaseEncoding.base64().encode(json.getBytes(Charset.defaultCharset()));
- secret = new SecretBuilder()
- .withNewMetadata()
- .withName(secretName)
- .endMetadata()
- .withType(KUBERNETES_DOCKERCFG)
- .withData(ImmutableMap.of(".dockercfg", base64encoded))
- .build();
- try {
- client.secrets().inNamespace(namespace).create(secret);
- } catch (KubernetesClientException e) {
- if (e.getCode() == 500 && e.getMessage().contains("Message: resourceVersion may not be set on objects to be created")) {
- // ignore exception as per https://github.com/fabric8io/kubernetes-client/issues/451
- } else {
- throw Throwables.propagate(e);
- }
- }
- ExitCondition exitCondition = new ExitCondition() {
- @Override
- public Boolean call() {
- return client.secrets().inNamespace(namespace).withName(secretName).get() != null;
- }
- @Override
- public String getFailureMessage() {
- return "Absent namespace=" + namespace + ", secretName=" + secretName;
- }
- };
- waitForExitCondition(exitCondition);
- return client.secrets().inNamespace(namespace).withName(secretName).get();
- }
-
- protected Container buildContainer(String namespace, Map<String, String> metadata, String deploymentName, String imageName, Iterable<Integer> inboundPorts, Map<String, ?> env, Map<String, String> limits, boolean privileged) {
- List<ContainerPort> containerPorts = Lists.newArrayList();
- for (Integer inboundPort : inboundPorts) {
- containerPorts.add(new ContainerPortBuilder().withContainerPort(inboundPort).build());
- }
-
- List<EnvVar> envVars = Lists.newArrayList();
- for (Map.Entry<String, ?> envVarEntry : env.entrySet()) {
- envVars.add(new EnvVarBuilder().withName(envVarEntry.getKey()).withValue(envVarEntry.getValue().toString()).build());
- }
-
- ContainerBuilder containerBuilder = new ContainerBuilder()
- .withName(deploymentName)
- .withImage(imageName)
- .addToPorts(Iterables.toArray(containerPorts, ContainerPort.class))
- .addToEnv(Iterables.toArray(envVars, EnvVar.class))
- .withNewSecurityContext()
- .withPrivileged(privileged)
- .endSecurityContext();
-
- if (limits != null) {
- for (Map.Entry<String, String> nameValueEntry : limits.entrySet()) {
- ResourceRequirements resourceRequirements = new ResourceRequirementsBuilder().addToLimits(nameValueEntry.getKey(), new QuantityBuilder().withAmount(nameValueEntry.getValue()).build()).build();
- containerBuilder.withResources(resourceRequirements);
- }
- }
- LOG.debug("Built container {} to be deployed in namespace {} with metadata {}.", containerBuilder.build(), namespace, metadata);
- return containerBuilder.build();
- }
-
- protected void deploy(final String namespace, Entity entity, Map<String, String> metadata, final String deploymentName, Container container, final Integer replicas, Map<String, String> secrets) {
- PodTemplateSpecBuilder podTemplateSpecBuilder = new PodTemplateSpecBuilder()
- .withNewMetadata()
- .addToLabels("name", deploymentName)
- .addToLabels(metadata)
- .endMetadata()
- .withNewSpec()
- .addToContainers(container)
- .endSpec();
- if (secrets != null) {
- for (String secretName : secrets.keySet()) {
- podTemplateSpecBuilder.withNewSpec()
- .addToContainers(container)
- .addNewImagePullSecret(secretName)
- .endSpec();
- }
- }
- PodTemplateSpec template = podTemplateSpecBuilder.build();
- Deployment deployment = new DeploymentBuilder()
- .withNewMetadata()
- .withName(deploymentName)
- .addToAnnotations(CLOUDSOFT_ENTITY_ID, entity.getId())
- .addToAnnotations(CLOUDSOFT_APPLICATION_ID, entity.getApplicationId())
- .endMetadata()
- .withNewSpec()
- .withReplicas(replicas)
- .withTemplate(template)
- .endSpec()
- .build();
- client.extensions().deployments().inNamespace(namespace).create(deployment);
- ExitCondition exitCondition = new ExitCondition() {
- @Override
- public Boolean call() {
- Deployment dep = client.extensions().deployments().inNamespace(namespace).withName(deploymentName).get();
- DeploymentStatus status = (dep == null) ? null : dep.getStatus();
- Integer replicas = (status == null) ? null : status.getAvailableReplicas();
- return replicas != null && replicas.intValue() == replicas;
- }
- @Override
- public String getFailureMessage() {
- Deployment dep = client.extensions().deployments().inNamespace(namespace).withName(deploymentName).get();
- DeploymentStatus status = (dep == null) ? null : dep.getStatus();
- return "Namespace=" + namespace + "; deploymentName= " + deploymentName + "; Deployment=" + dep
- + "; status=" + status
- + "; availableReplicas=" + (status == null ? "null" : status.getAvailableReplicas());
- }
- };
- waitForExitCondition(exitCondition);
- LOG.debug("Deployed deployment {} in namespace {}.", deployment, namespace);
- }
-
- protected Service exposeService(String namespace, Map<String, String> metadata, String serviceName, Iterable<Integer> inboundPorts) {
- List<ServicePort> servicePorts = Lists.newArrayList();
- for (Integer inboundPort : inboundPorts) {
- servicePorts.add(new ServicePortBuilder().withName(Integer.toString(inboundPort)).withPort(inboundPort).build());
- }
- Service service = new ServiceBuilder().withNewMetadata().withName(serviceName).endMetadata()
- .withNewSpec()
- .addToSelector(metadata)
- .addToPorts(Iterables.toArray(servicePorts, ServicePort.class))
- .withType(NODE_PORT)
- .endSpec()
- .build();
- client.services().inNamespace(namespace).create(service);
-
- service = getService(namespace, serviceName);
- LOG.debug("Exposed service {} in namespace {}.", service, namespace);
- return service;
- }
-
- protected Service getService(final String namespace, final String serviceName) {
- ExitCondition exitCondition = new ExitCondition() {
- @Override
- public Boolean call() {
- Service svc = client.services().inNamespace(namespace).withName(serviceName).get();
- if (svc == null || svc.getStatus() == null) {
- return false;
- }
- Endpoints endpoints = client.endpoints().inNamespace(namespace).withName(serviceName).get();
- if (endpoints == null || endpoints.getSubsets().isEmpty()) {
- return false;
- }
- for (EndpointSubset subset : endpoints.getSubsets()) {
- if (subset.getNotReadyAddresses().size() > 0) {
- return false;
- }
- }
- return true;
- }
- @Override
- public String getFailureMessage() {
- Endpoints endpoints = client.endpoints().inNamespace(namespace).withName(serviceName).get();
- return "Service endpoints in " + namespace + " for serviceName= " + serviceName + " not ready: " + endpoints;
- }
- };
- waitForExitCondition(exitCondition);
-
- return client.services().inNamespace(namespace).withName(serviceName).get();
- }
-
- protected LocationSpec<KubernetesSshMachineLocation> prepareSshableLocationSpec(Entity entity, ConfigBag setup, Namespace namespace, String deploymentName, Service service, Pod pod) {
- InetAddress node = Networking.getInetAddressWithFixedName(pod.getSpec().getNodeName());
- String podAddress = pod.getStatus().getPodIP();
- LocationSpec<KubernetesSshMachineLocation> locationSpec = LocationSpec.create(KubernetesSshMachineLocation.class)
- .configure("address", node)
- .configure(SshMachineLocation.PRIVATE_ADDRESSES, ImmutableSet.of(podAddress))
- .configure(CALLER_CONTEXT, setup.get(CALLER_CONTEXT));
- if (!isDockerContainer(entity)) {
- Optional<ServicePort> sshPort = Iterables.tryFind(service.getSpec().getPorts(), new Predicate<ServicePort>() {
- @Override
- public boolean apply(ServicePort input) {
- return input.getProtocol().equalsIgnoreCase("TCP") && input.getPort().intValue() == 22;
- }
- });
- Optional<Integer> sshPortNumber;
- if (sshPort.isPresent()) {
- sshPortNumber = Optional.of(sshPort.get().getNodePort());
- } else {
- LOG.warn("No port-mapping found to ssh port 22, for container {}", service);
- sshPortNumber = Optional.absent();
- }
- locationSpec.configure(CloudLocationConfig.USER, setup.get(KubernetesLocationConfig.LOGIN_USER))
- .configure(SshMachineLocation.PASSWORD, setup.get(KubernetesLocationConfig.LOGIN_USER_PASSWORD))
- .configureIfNotNull(SshMachineLocation.SSH_PORT, sshPortNumber.orNull())
- .configure(BrooklynConfigKeys.SKIP_ON_BOX_BASE_DIR_RESOLUTION, true)
- .configure(BrooklynConfigKeys.ONBOX_BASE_DIR, "/tmp");
- }
- return locationSpec;
- }
-
- protected void createPersistentVolumes(List<String> volumes) {
- for (final String persistentVolume : volumes) {
- PersistentVolume volume = new PersistentVolumeBuilder()
- .withNewMetadata()
- .withName(persistentVolume)
- .withLabels(ImmutableMap.of("type", "local")) // TODO make it configurable
- .endMetadata()
- .withNewSpec()
- .addToCapacity("storage", new QuantityBuilder().withAmount("20").build()) // TODO make it configurable
- .addToAccessModes("ReadWriteOnce") // TODO make it configurable
- .withNewHostPath().withPath("/tmp/pv-1").endHostPath() // TODO make it configurable
- .endSpec()
- .build();
- client.persistentVolumes().create(volume);
- ExitCondition exitCondition = new ExitCondition() {
- @Override
- public Boolean call() {
- PersistentVolume pv = client.persistentVolumes().withName(persistentVolume).get();
- return pv != null && pv.getStatus() != null
- && pv.getStatus().getPhase().equals(PHASE_AVAILABLE);
- }
- @Override
- public String getFailureMessage() {
- PersistentVolume pv = client.persistentVolumes().withName(persistentVolume).get();
- return "PersistentVolume for " + persistentVolume + " " + (pv == null ? "absent" : "pv=" + pv);
- }
- };
- waitForExitCondition(exitCondition);
- }
- }
-
- protected Entity validateCallerContext(ConfigBag setup) {
- // Lookup entity flags
- Object callerContext = setup.get(LocationConfigKeys.CALLER_CONTEXT);
- if (callerContext instanceof Entity) {
- return (Entity) callerContext;
- } else {
- throw new IllegalStateException("Invalid caller context: " + callerContext);
- }
- }
-
- protected Entity validateCallerContext(MachineLocation machine) {
- // Lookup entity flags
- Object callerContext = machine.config().get(LocationConfigKeys.CALLER_CONTEXT);
- if (callerContext instanceof Entity) {
- return (Entity) callerContext;
- } else {
- throw new IllegalStateException("Invalid caller context: " + callerContext);
- }
- }
-
- protected Map<String, String> findMetadata(Entity entity, ConfigBag setup, String value) {
- Map<String, String> podMetadata = Maps.newLinkedHashMap();
- if (isDockerContainer(entity)) {
- podMetadata.put(IMMUTABLE_CONTAINER_KEY, value);
- } else {
- podMetadata.put(SSHABLE_CONTAINER, value);
- }
-
- Map<String, Object> metadata = MutableMap.<String, Object>builder()
- .putAll(MutableMap.copyOf(setup.get(KubernetesPod.METADATA)))
- .putAll(MutableMap.copyOf(entity.config().get(KubernetesPod.METADATA)))
- .putAll(podMetadata)
- .build();
- return Maps.transformValues(metadata, Functions.toStringFunction());
- }
-
- /**
- * Sets the {@code CLOUDSOFT_ROOT_PASSWORD} variable in the container environment if appropriate.
- * This is (approximately) the same behaviour as the {@link DockerJcloudsLocation} used for
- * Swarm.
- *
- * Side-effects the location {@code config} to set the {@link KubernetesLocationConfig#LOGIN_USER_PASSWORD loginUser.password}
- * if one is auto-generated. Note that this injected value overrides any other settings configured for the
- * container environment.
- */
- protected Map<String, String> findEnvironmentVariables(Entity entity, ConfigBag setup, String imageName) {
- String loginUser = setup.get(LOGIN_USER);
- String loginPassword = setup.get(LOGIN_USER_PASSWORD);
- Map<String, String> injections = Maps.newLinkedHashMap();
-
- // Check if login credentials should be injected
- Boolean injectLoginCredentials = setup.get(INJECT_LOGIN_CREDENTIAL);
- if (injectLoginCredentials == null) {
- for (String regex : IMAGE_DESCRIPTION_REGEXES_REQUIRING_INJECTED_LOGIN_CREDS) {
- if (imageName != null && imageName.matches(regex)) {
- injectLoginCredentials = true;
- break;
- }
- }
- }
-
- if (Boolean.TRUE.equals(injectLoginCredentials)) {
- if ((Strings.isBlank(loginUser) || "root".equals(loginUser))) {
- loginUser = "root";
- setup.configure(LOGIN_USER, loginUser);
-
- if (Strings.isBlank(loginPassword)) {
- loginPassword = Identifiers.makeRandomPassword(12);
- setup.configure(LOGIN_USER_PASSWORD, loginPassword);
- }
-
- injections.put(CLOUDSOFT_ROOT_PASSWORD, loginPassword);
- }
- }
-
- Map<String,Object> rawEnv = MutableMap.<String, Object>builder()
- .putAll(MutableMap.copyOf(setup.get(ENV)))
- .putAll(MutableMap.copyOf(entity.config().get(DockerContainer.CONTAINER_ENVIRONMENT)))
- .putAll(injections)
- .build();
- return Maps.transformValues(rawEnv, Functions.toStringFunction());
- }
-
- protected Iterable<Integer> findInboundPorts(Entity entity, ConfigBag setup) {
- Iterable<String> inboundTcpPorts = entity.config().get(DockerContainer.INBOUND_TCP_PORTS);
- if (inboundTcpPorts != null) {
- List<Integer> inboundPorts = Lists.newArrayList();
- List<String> portRanges = MutableList.copyOf(entity.config().get(DockerContainer.INBOUND_TCP_PORTS));
- for (String portRange : portRanges) {
- for (Integer port : PortRanges.fromString(portRange)) {
- inboundPorts.add(port);
- }
- }
- return inboundPorts;
- } else {
- if (setup.containsKey(INBOUND_PORTS)) {
- return toIntPortList(setup.get(INBOUND_PORTS));
- } else {
- return ImmutableList.of(22);
- }
- }
- }
-
- protected List<Integer> toIntPortList(Object v) {
- if (v == null) return ImmutableList.of();
- PortRange portRange = PortRanges.fromIterable(ImmutableList.of(v));
- return ImmutableList.copyOf(portRange);
- }
-
- protected String findImageName(Entity entity, ConfigBag setup) {
- String result = entity.config().get(DockerContainer.IMAGE_NAME);
- if (Strings.isNonBlank(result)) return result;
-
- result = setup.get(IMAGE);
- if (Strings.isNonBlank(result)) return result;
-
- String osFamily = setup.get(OS_FAMILY);
- String osVersion = setup.get(OS_VERSION_REGEX);
- Optional<String> imageName = new ImageChooser().chooseImage(osFamily, osVersion);
- if (imageName.isPresent()) return imageName.get();
-
- throw new IllegalStateException("No matching image found for " + entity
- + " (no explicit image name, osFamily=" + osFamily + "; osVersion=" + osVersion + ")");
- }
-
- protected boolean isDockerContainer(Entity entity) {
- return implementsInterface(entity, DockerContainer.class);
- }
-
- protected boolean isKubernetesPod(Entity entity) {
- return implementsInterface(entity, KubernetesPod.class);
- }
-
- protected boolean isKubernetesResource(Entity entity) {
- return implementsInterface(entity, KubernetesResource.class);
- }
-
- public boolean implementsInterface(Entity entity, Class<?> type) {
- return Iterables.tryFind(Arrays.asList(entity.getClass().getInterfaces()), Predicates.assignableFrom(type)).isPresent();
- }
-
- @Override
- public MachineProvisioningLocation<KubernetesMachineLocation> newSubLocation(Map<?, ?> newFlags) {
- throw new UnsupportedOperationException();
- }
-
- /** @see {@link #lookup(ConfigKey, Entity, ConfigBag, Object)} */
- public <T> T lookup(ConfigKey<T> config, Entity entity, ConfigBag setup) {
- return lookup(config, entity, setup, null);
- }
-
- /**
- * Looks up {@link ConfigKey configuration} with the entity value taking precedence over the
- * location, and returning a default value (normally {@literal null}) if neither is present.
- */
- public <T> T lookup(ConfigKey<T> config, Entity entity, ConfigBag setup, T defaultValue) {
- Optional<T> entityValue = Optional.fromNullable(entity.config().get(config));
- Optional<T> locationValue = Optional.fromNullable(setup.get(config));
-
- return Iterables.getFirst(Optional.presentInstances(Arrays.asList(entityValue, locationValue)), defaultValue);
- }
-
- public void waitForExitCondition(ExitCondition exitCondition) {
- waitForExitCondition(exitCondition, Duration.ONE_SECOND, Duration.FIVE_MINUTES);
- }
-
- public void waitForExitCondition(ExitCondition exitCondition, Duration initial, Duration duration) {
- ReferenceWithError<Boolean> result = Repeater.create()
- .backoff(initial, 1.2, duration)
- .limitTimeTo(duration)
- .until(exitCondition)
- .runKeepingError();
- if (!result.get()) {
- String err = "Exit condition unsatisfied after " + duration + ": " + exitCondition.getFailureMessage();
- LOG.info(err + " (rethrowing)");
- throw new IllegalStateException(err);
- }
- }
-
- public static interface ExitCondition extends Callable<Boolean> {
- public String getFailureMessage();
- }
-}
http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/445884b1/kubernetes-location/src/main/java/io/cloudsoft/amp/containerservice/kubernetes/location/KubernetesLocationConfig.java
----------------------------------------------------------------------
diff --git a/kubernetes-location/src/main/java/io/cloudsoft/amp/containerservice/kubernetes/location/KubernetesLocationConfig.java b/kubernetes-location/src/main/java/io/cloudsoft/amp/containerservice/kubernetes/location/KubernetesLocationConfig.java
deleted file mode 100644
index 0571fc2..0000000
--- a/kubernetes-location/src/main/java/io/cloudsoft/amp/containerservice/kubernetes/location/KubernetesLocationConfig.java
+++ /dev/null
@@ -1,164 +0,0 @@
-package io.cloudsoft.amp.containerservice.kubernetes.location;
-
-import java.util.Map;
-
-import org.apache.brooklyn.config.ConfigKey;
-import org.apache.brooklyn.core.config.ConfigKeys;
-import org.apache.brooklyn.core.location.LocationConfigKeys;
-import org.apache.brooklyn.core.location.cloud.CloudLocationConfig;
-import org.apache.brooklyn.util.time.Duration;
-
-import com.google.common.base.Predicates;
-import com.google.common.collect.ImmutableMap;
-import com.google.common.reflect.TypeToken;
-
-public interface KubernetesLocationConfig extends CloudLocationConfig {
-
- ConfigKey<String> MASTER_URL = LocationConfigKeys.CLOUD_ENDPOINT;
-
- ConfigKey<String> CA_CERT_DATA = ConfigKeys.builder(String.class)
- .name("caCertData")
- .description("Data for CA certificate")
- .constraint(Predicates.<String>notNull())
- .build();
-
- ConfigKey<String> CA_CERT_FILE = ConfigKeys.builder(String.class)
- .name("caCertFile")
- .description("URL of resource containing CA certificate data")
- .constraint(Predicates.<String>notNull())
- .build();
-
- ConfigKey<String> CLIENT_CERT_DATA = ConfigKeys.builder(String.class)
- .name("clientCertData")
- .description("Data for client certificate")
- .constraint(Predicates.<String>notNull())
- .build();
-
- ConfigKey<String> CLIENT_CERT_FILE = ConfigKeys.builder(String.class)
- .name("clientCertFile")
- .description("URL of resource containing client certificate data")
- .constraint(Predicates.<String>notNull())
- .build();
-
- ConfigKey<String> CLIENT_KEY_DATA = ConfigKeys.builder(String.class)
- .name("clientKeyData")
- .description("Data for client key")
- .constraint(Predicates.<String>notNull())
- .build();
-
- ConfigKey<String> CLIENT_KEY_FILE = ConfigKeys.builder(String.class)
- .name("clientKeyFile")
- .description("URL of resource containing client key data")
- .constraint(Predicates.<String>notNull())
- .build();
-
- ConfigKey<String> CLIENT_KEY_ALGO = ConfigKeys.builder(String.class)
- .name("clientKeyAlgo")
- .description("Algorithm used for the client key")
- .constraint(Predicates.<String>notNull())
- .build();
-
- ConfigKey<String> CLIENT_KEY_PASSPHRASE = ConfigKeys.builder(String.class)
- .name("clientKeyPassphrase")
- .description("Passphrase used for the client key")
- .constraint(Predicates.<String>notNull())
- .build();
-
- ConfigKey<String> OAUTH_TOKEN = ConfigKeys.builder(String.class)
- .name("oauthToken")
- .description("The OAuth token data for the current user")
- .constraint(Predicates.<String>notNull())
- .build();
-
- ConfigKey<Duration> CLIENT_TIMEOUT = ConfigKeys.builder(Duration.class)
- .name("timeout")
- .description("The timeout for the client")
- .defaultValue(Duration.seconds(10))
- .constraint(Predicates.<Duration>notNull())
- .build();
-
- ConfigKey<Duration> ACTION_TIMEOUT = ConfigKeys.builder(Duration.class)
- .name("actionTimeout")
- .description("The timeout for Kubernetes actions")
- .defaultValue(Duration.ONE_MINUTE)
- .constraint(Predicates.<Duration>notNull())
- .build();
-
- ConfigKey<Boolean> CREATE_NAMESPACE = ConfigKeys.builder(Boolean.class)
- .name("namespace.create")
- .description("Whether to create the namespace if it does not exist")
- .defaultValue(true)
- .constraint(Predicates.<Boolean>notNull())
- .build();
-
- ConfigKey<Boolean> DELETE_EMPTY_NAMESPACE = ConfigKeys.builder(Boolean.class)
- .name("namespace.deleteEmpty")
- .description("Whether to delete an empty namespace when releasing resources")
- .defaultValue(false)
- .constraint(Predicates.<Boolean>notNull())
- .build();
-
- ConfigKey<String> NAMESPACE = ConfigKeys.builder(String.class)
- .name("namespace")
- .description("Namespace where resources will live; the default is 'amp'")
- .defaultValue("amp")
- .constraint(Predicates.<String>notNull())
- .build();
-
- ConfigKey<Boolean> PRIVILEGED = ConfigKeys.builder(Boolean.class)
- .name("privileged")
- .description("Whether the pods use privileged containers")
- .defaultValue(false)
- .build();
-
- @SuppressWarnings("serial")
- ConfigKey<Map<String, ?>> ENV = ConfigKeys.builder(new TypeToken<Map<String, ?>>() {})
- .name("env")
- .description("Environment variables to inject when starting the container")
- .defaultValue(ImmutableMap.<String, Object>of())
- .constraint(Predicates.<Map<String, ?>>notNull())
- .build();
-
- ConfigKey<String> IMAGE = ConfigKeys.builder(String.class)
- .name("image")
- .description("Docker image to be deployed into the pod")
- .constraint(Predicates.<String>notNull())
- .build();
-
- ConfigKey<String> OS_FAMILY = ConfigKeys.builder(String.class)
- .name("osFamily")
- .description("OS family, e.g. CentOS, Ubuntu")
- .build();
-
- ConfigKey<String> OS_VERSION_REGEX = ConfigKeys.builder(String.class)
- .name("osVersionRegex")
- .description("Regular expression for the OS version to load")
- .build();
-
- ConfigKey<KubernetesClientRegistry> KUBERNETES_CLIENT_REGISTRY = ConfigKeys.builder(KubernetesClientRegistry.class)
- .name("kubernetesClientRegistry")
- .description("Registry/Factory for creating Kubernetes client; default is almost always fine, "
- + "except where tests want to customize behaviour")
- .defaultValue(KubernetesClientRegistryImpl.INSTANCE)
- .build();
-
- ConfigKey<String> LOGIN_USER = ConfigKeys.builder(String.class)
- .name("loginUser")
- .description("Override the user who logs in initially to perform setup")
- .defaultValue("root")
- .constraint(Predicates.<String>notNull())
- .build();
-
- ConfigKey<String> LOGIN_USER_PASSWORD = ConfigKeys.builder(String.class)
- .name("loginUser.password")
- .description("Custom password for the user who logs in initially")
- .constraint(Predicates.<String>notNull())
- .build();
-
- ConfigKey<Boolean> INJECT_LOGIN_CREDENTIAL = ConfigKeys.builder(Boolean.class)
- .name("injectLoginCredential")
- .description("Whether to inject login credentials (if null, will infer from image choice); ignored if explicit 'loginUser.password' supplied")
- .build();
-
-}
-
http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/445884b1/kubernetes-location/src/main/java/io/cloudsoft/amp/containerservice/kubernetes/location/KubernetesLocationResolver.java
----------------------------------------------------------------------
diff --git a/kubernetes-location/src/main/java/io/cloudsoft/amp/containerservice/kubernetes/location/KubernetesLocationResolver.java b/kubernetes-location/src/main/java/io/cloudsoft/amp/containerservice/kubernetes/location/KubernetesLocationResolver.java
deleted file mode 100644
index 79e7c64..0000000
--- a/kubernetes-location/src/main/java/io/cloudsoft/amp/containerservice/kubernetes/location/KubernetesLocationResolver.java
+++ /dev/null
@@ -1,47 +0,0 @@
-package io.cloudsoft.amp.containerservice.kubernetes.location;
-
-import org.apache.brooklyn.api.location.Location;
-import org.apache.brooklyn.api.location.LocationResolver;
-import org.apache.brooklyn.core.location.AbstractLocationResolver;
-import org.apache.brooklyn.core.location.LocationConfigUtils;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-/**
- * Locations starting with the given prefix (@code "kubernetes") will use this resolver, to instantiate
- * a {@link KubernetesLocation}.
- *
- * We ensure that config will be picked up from brooklyn.properties using the appropriate precedence:
- * <ol>
- * <li>named location config
- * <li>Prefix {@code brooklyn.location.kubernetes.}
- * <li>Prefix {@code brooklyn.kubernetes.}
- * </ol>
- */
-public class KubernetesLocationResolver extends AbstractLocationResolver implements LocationResolver {
-
- public static final Logger log = LoggerFactory.getLogger(KubernetesLocationResolver.class);
-
- public static final String PREFIX = "kubernetes";
-
- @Override
- public boolean isEnabled() {
- return LocationConfigUtils.isResolverPrefixEnabled(managementContext, getPrefix());
- }
-
- @Override
- public String getPrefix() {
- return PREFIX;
- }
-
- @Override
- protected Class<? extends Location> getLocationType() {
- return KubernetesLocation.class;
- }
-
- @Override
- protected SpecParser getSpecParser() {
- return new SpecParser(getPrefix()).setExampleUsage("\"kubernetes\"");
- }
-
-}
http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/445884b1/kubernetes-location/src/main/java/io/cloudsoft/amp/containerservice/kubernetes/location/machine/KubernetesEmptyMachineLocation.java
----------------------------------------------------------------------
diff --git a/kubernetes-location/src/main/java/io/cloudsoft/amp/containerservice/kubernetes/location/machine/KubernetesEmptyMachineLocation.java b/kubernetes-location/src/main/java/io/cloudsoft/amp/containerservice/kubernetes/location/machine/KubernetesEmptyMachineLocation.java
deleted file mode 100644
index 8875ef3..0000000
--- a/kubernetes-location/src/main/java/io/cloudsoft/amp/containerservice/kubernetes/location/machine/KubernetesEmptyMachineLocation.java
+++ /dev/null
@@ -1,68 +0,0 @@
-package io.cloudsoft.amp.containerservice.kubernetes.location.machine;
-
-import java.net.InetAddress;
-import java.util.Set;
-
-import org.apache.brooklyn.api.location.MachineDetails;
-import org.apache.brooklyn.api.location.MachineLocation;
-import org.apache.brooklyn.api.location.OsDetails;
-import org.apache.brooklyn.location.ssh.SshMachineLocation;
-import org.apache.brooklyn.util.net.Networking;
-
-import com.google.common.collect.ImmutableSet;
-
-/**
- * A {@link MachineLocation} represemnting a Kubernetes resource that does not support SSH access.
- *
- * @see {@link KubernetesSshMachineLocation}
- */
-public class KubernetesEmptyMachineLocation extends SshMachineLocation implements KubernetesMachineLocation {
-
- @Override
- public String getHostname() {
- return getResourceName();
- }
-
- @Override
- public Set<String> getPublicAddresses() {
- return ImmutableSet.of("0.0.0.0");
- }
-
- @Override
- public Set<String> getPrivateAddresses() {
- return ImmutableSet.of("0.0.0.0");
- }
-
- @Override
- public InetAddress getAddress() {
- return Networking.getInetAddressWithFixedName("0.0.0.0");
- }
-
- @Override
- public OsDetails getOsDetails() {
- return null;
- // throw new UnsupportedOperationException("No OS details for empty KubernetesMachineLocation");
- }
-
- @Override
- public MachineDetails getMachineDetails() {
- return null;
- // throw new UnsupportedOperationException("No machine details for empty KubernetesMachineLocation");
- }
-
- @Override
- public String getResourceName() {
- return config().get(KUBERNETES_RESOURCE_NAME);
- }
-
- @Override
- public String getResourceType() {
- return config().get(KUBERNETES_RESOURCE_TYPE);
- }
-
- @Override
- public String getNamespace() {
- return config().get(KUBERNETES_NAMESPACE);
- }
-
-}
http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/445884b1/kubernetes-location/src/main/java/io/cloudsoft/amp/containerservice/kubernetes/location/machine/KubernetesMachineLocation.java
----------------------------------------------------------------------
diff --git a/kubernetes-location/src/main/java/io/cloudsoft/amp/containerservice/kubernetes/location/machine/KubernetesMachineLocation.java b/kubernetes-location/src/main/java/io/cloudsoft/amp/containerservice/kubernetes/location/machine/KubernetesMachineLocation.java
deleted file mode 100644
index 6d8838b..0000000
--- a/kubernetes-location/src/main/java/io/cloudsoft/amp/containerservice/kubernetes/location/machine/KubernetesMachineLocation.java
+++ /dev/null
@@ -1,27 +0,0 @@
-package io.cloudsoft.amp.containerservice.kubernetes.location.machine;
-
-import org.apache.brooklyn.api.location.MachineLocation;
-import org.apache.brooklyn.config.ConfigKey;
-import org.apache.brooklyn.core.config.ConfigKeys;
-
-public interface KubernetesMachineLocation extends MachineLocation {
-
- ConfigKey<String> KUBERNETES_NAMESPACE = ConfigKeys.builder(String.class, "kubernetes.namespace")
- .description("Namespace for the KubernetesMachineLocation")
- .build();
-
- ConfigKey<String> KUBERNETES_RESOURCE_NAME = ConfigKeys.builder(String.class, "kubernetes.name")
- .description("Name of the resource represented by the KubernetesMachineLocation")
- .build();
-
- ConfigKey<String> KUBERNETES_RESOURCE_TYPE = ConfigKeys.builder(String.class, "kubernetes.type")
- .description("Type of the resource represented by the KubernetesMachineLocation")
- .build();
-
- public String getResourceName();
-
- public String getResourceType();
-
- public String getNamespace();
-
-}
http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/445884b1/kubernetes-location/src/main/java/io/cloudsoft/amp/containerservice/kubernetes/location/machine/KubernetesSshMachineLocation.java
----------------------------------------------------------------------
diff --git a/kubernetes-location/src/main/java/io/cloudsoft/amp/containerservice/kubernetes/location/machine/KubernetesSshMachineLocation.java b/kubernetes-location/src/main/java/io/cloudsoft/amp/containerservice/kubernetes/location/machine/KubernetesSshMachineLocation.java
deleted file mode 100644
index ad83f8f..0000000
--- a/kubernetes-location/src/main/java/io/cloudsoft/amp/containerservice/kubernetes/location/machine/KubernetesSshMachineLocation.java
+++ /dev/null
@@ -1,28 +0,0 @@
-package io.cloudsoft.amp.containerservice.kubernetes.location.machine;
-
-import org.apache.brooklyn.api.location.MachineLocation;
-import org.apache.brooklyn.location.ssh.SshMachineLocation;
-
-/**
- * A {@link MachineLocation} represemnting a Kubernetes resource that allows SSH access.
- *
- * @see {@link KubernetesSshMachineLocation}
- */
-public class KubernetesSshMachineLocation extends SshMachineLocation implements KubernetesMachineLocation {
-
- @Override
- public String getResourceName() {
- return config().get(KUBERNETES_RESOURCE_NAME);
- }
-
- @Override
- public String getResourceType() {
- return config().get(KUBERNETES_RESOURCE_TYPE);
- }
-
- @Override
- public String getNamespace() {
- return config().get(KUBERNETES_NAMESPACE);
- }
-
-}
http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/445884b1/kubernetes-location/src/test/java/io/cloudsoft/amp/containerservice/kubernetes/location/ImageChooserTest.java
----------------------------------------------------------------------
diff --git a/kubernetes-location/src/test/java/io/cloudsoft/amp/containerservice/kubernetes/location/ImageChooserTest.java b/kubernetes-location/src/test/java/io/cloudsoft/amp/containerservice/kubernetes/location/ImageChooserTest.java
deleted file mode 100644
index 8f28929..0000000
--- a/kubernetes-location/src/test/java/io/cloudsoft/amp/containerservice/kubernetes/location/ImageChooserTest.java
+++ /dev/null
@@ -1,67 +0,0 @@
-package io.cloudsoft.amp.containerservice.kubernetes.location;
-
-import static org.testng.Assert.assertEquals;
-import static org.testng.Assert.assertFalse;
-
-import org.testng.annotations.BeforeMethod;
-import org.testng.annotations.Test;
-
-public class ImageChooserTest {
-
- private ImageChooser chooser;
-
- @BeforeMethod(alwaysRun=true)
- public void setUp() {
- chooser = new ImageChooser();
- }
-
- @Test
- public void testDefault() throws Exception {
- assertEquals(chooser.chooseImage((String)null, null).get(), "cloudsoft/centos:7");
- }
-
- @Test
- public void testCentos() throws Exception {
- assertEquals(chooser.chooseImage("cEnToS", null).get(), "cloudsoft/centos:7");
- }
-
- @Test
- public void testCentos7() throws Exception {
- assertEquals(chooser.chooseImage("cEnToS", "7").get(), "cloudsoft/centos:7");
- }
-
- @Test
- public void testUbnutu() throws Exception {
- assertEquals(chooser.chooseImage("uBuNtU", null).get(), "cloudsoft/ubuntu:14.04");
- }
-
- @Test
- public void testUbnutu14() throws Exception {
- assertEquals(chooser.chooseImage("uBuNtU", "14.*").get(), "cloudsoft/ubuntu:14.04");
- }
-
- @Test
- public void testUbnutu16() throws Exception {
- assertEquals(chooser.chooseImage("uBuNtU", "16.*").get(), "cloudsoft/ubuntu:16.04");
- }
-
- @Test
- public void testAbsentForCentos6() throws Exception {
- assertFalse(chooser.chooseImage("cEnToS", "6").isPresent());
- }
-
- @Test
- public void testAbsentForUbuntu15() throws Exception {
- assertFalse(chooser.chooseImage("uBuNtU", "15").isPresent());
- }
-
- @Test
- public void testAbsentForDebian() throws Exception {
- assertFalse(chooser.chooseImage("debian", null).isPresent());
- }
-
- @Test
- public void testAbsentForWrongOsFamily() throws Exception {
- assertFalse(chooser.chooseImage("weirdOsFamily", null).isPresent());
- }
-}
http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/445884b1/kubernetes-location/src/test/java/io/cloudsoft/amp/containerservice/kubernetes/location/KubernetesCertsTest.java
----------------------------------------------------------------------
diff --git a/kubernetes-location/src/test/java/io/cloudsoft/amp/containerservice/kubernetes/location/KubernetesCertsTest.java b/kubernetes-location/src/test/java/io/cloudsoft/amp/containerservice/kubernetes/location/KubernetesCertsTest.java
deleted file mode 100644
index 27c1b79..0000000
--- a/kubernetes-location/src/test/java/io/cloudsoft/amp/containerservice/kubernetes/location/KubernetesCertsTest.java
+++ /dev/null
@@ -1,146 +0,0 @@
-package io.cloudsoft.amp.containerservice.kubernetes.location;
-
-import static org.testng.Assert.assertEquals;
-import static org.testng.Assert.assertFalse;
-
-import java.io.File;
-import java.util.List;
-
-import org.apache.brooklyn.test.Asserts;
-import org.apache.brooklyn.test.LogWatcher;
-import org.apache.brooklyn.test.LogWatcher.EventPredicates;
-import org.apache.brooklyn.util.core.config.ConfigBag;
-import org.apache.brooklyn.util.text.Identifiers;
-import org.testng.annotations.AfterMethod;
-import org.testng.annotations.BeforeMethod;
-import org.testng.annotations.Test;
-
-import com.google.common.base.Charsets;
-import com.google.common.base.Predicate;
-import com.google.common.collect.ImmutableMap;
-import com.google.common.collect.Lists;
-import com.google.common.io.Files;
-
-import ch.qos.logback.classic.spi.ILoggingEvent;
-
-public class KubernetesCertsTest {
-
- private List<File> tempFiles;
-
- @BeforeMethod(alwaysRun=true)
- public void setUp() throws Exception {
- tempFiles = Lists.newArrayList();
- }
-
- @AfterMethod(alwaysRun=true)
- public void tearDown() throws Exception {
- if (tempFiles != null) {
- for (File tempFile : tempFiles) {
- tempFile.delete();
- }
- }
- }
-
- @Test
- public void testCertsAbsent() throws Exception {
- ConfigBag config = ConfigBag.newInstance();
- KubernetesCerts certs = new KubernetesCerts(config);
-
- assertFalse(certs.caCertData.isPresent());
- assertFalse(certs.clientCertData.isPresent());
- assertFalse(certs.clientKeyData.isPresent());
- assertFalse(certs.clientKeyAlgo.isPresent());
- assertFalse(certs.clientKeyPassphrase.isPresent());
- }
-
- @Test
- public void testCertsFromData() throws Exception {
- ConfigBag config = ConfigBag.newInstance(ImmutableMap.builder()
- .put(KubernetesLocationConfig.CA_CERT_DATA, "myCaCertData")
- .put(KubernetesLocationConfig.CLIENT_CERT_DATA, "myClientCertData")
- .put(KubernetesLocationConfig.CLIENT_KEY_DATA, "myClientKeyData")
- .put(KubernetesLocationConfig.CLIENT_KEY_ALGO, "myClientKeyAlgo")
- .put(KubernetesLocationConfig.CLIENT_KEY_PASSPHRASE, "myClientKeyPassphrase")
- .build());
- KubernetesCerts certs = new KubernetesCerts(config);
-
- assertEquals(certs.caCertData.get(), "myCaCertData");
- assertEquals(certs.clientCertData.get(), "myClientCertData");
- assertEquals(certs.clientKeyData.get(), "myClientKeyData");
- assertEquals(certs.clientKeyAlgo.get(), "myClientKeyAlgo");
- assertEquals(certs.clientKeyPassphrase.get(), "myClientKeyPassphrase");
- }
-
- @Test
- public void testCertsFromFile() throws Exception {
- ConfigBag config = ConfigBag.newInstance(ImmutableMap.builder()
- .put(KubernetesLocationConfig.CA_CERT_FILE, newTempFile("myCaCertData").getAbsolutePath())
- .put(KubernetesLocationConfig.CLIENT_CERT_FILE, newTempFile("myClientCertData").getAbsolutePath())
- .put(KubernetesLocationConfig.CLIENT_KEY_FILE, newTempFile("myClientKeyData").getAbsolutePath())
- .build());
- KubernetesCerts certs = new KubernetesCerts(config);
-
- assertEquals(certs.caCertData.get(), "myCaCertData");
- assertEquals(certs.clientCertData.get(), "myClientCertData");
- assertEquals(certs.clientKeyData.get(), "myClientKeyData");
- }
-
- @Test
- public void testCertsFailsIfConflictingConfig() throws Exception {
- ConfigBag config = ConfigBag.newInstance(ImmutableMap.builder()
- .put(KubernetesLocationConfig.CA_CERT_DATA, "myCaCertData")
- .put(KubernetesLocationConfig.CA_CERT_FILE, newTempFile("differentCaCertData").getAbsolutePath())
- .build());
- try {
- new KubernetesCerts(config);
- Asserts.shouldHaveFailedPreviously();
- } catch (Exception e) {
- Asserts.expectedFailureContains(e, "Duplicate conflicting configuration for caCertData and caCertFile");
- }
- }
-
- @Test
- public void testCertsWarnsIfConflictingConfig() throws Exception {
- ConfigBag config = ConfigBag.newInstance(ImmutableMap.builder()
- .put(KubernetesLocationConfig.CA_CERT_DATA, "myCaCertData")
- .put(KubernetesLocationConfig.CA_CERT_FILE, newTempFile("myCaCertData").getAbsolutePath())
- .build());
-
- String loggerName = KubernetesCerts.class.getName();
- ch.qos.logback.classic.Level logLevel = ch.qos.logback.classic.Level.WARN;
- Predicate<ILoggingEvent> filter = EventPredicates.containsMessage("Duplicate (matching) configuration for "
- + "caCertData and caCertFile (continuing)");
- LogWatcher watcher = new LogWatcher(loggerName, logLevel, filter);
-
- watcher.start();
- KubernetesCerts certs;
- try {
- certs = new KubernetesCerts(config);
- watcher.assertHasEvent();
- } finally {
- watcher.close();
- }
-
- assertEquals(certs.caCertData.get(), "myCaCertData");
- }
-
- @Test
- public void testCertsFailsIfFileNotFound() throws Exception {
- ConfigBag config = ConfigBag.newInstance(ImmutableMap.builder()
- .put(KubernetesLocationConfig.CA_CERT_FILE, "/path/to/fileDoesNotExist-"+Identifiers.makeRandomId(8))
- .build());
- try {
- new KubernetesCerts(config);
- Asserts.shouldHaveFailedPreviously();
- } catch (Exception e) {
- Asserts.expectedFailureContains(e, "not found on classpath or filesystem");
- }
- }
-
- private File newTempFile(String contents) throws Exception {
- File file = File.createTempFile("KubernetesCertsTest", ".txt");
- tempFiles.add(file);
- Files.write(contents, file, Charsets.UTF_8);
- return file;
- }
-}