Package io.fabric8.kubernetes.provider

Source Code of io.fabric8.kubernetes.provider.KubernetesContainerProvider

/**
*  Copyright 2005-2014 Red Hat, Inc.
*
*  Red Hat 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 io.fabric8.kubernetes.provider;

import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.ObjectReader;
import io.fabric8.api.Constants;
import io.fabric8.api.Container;
import io.fabric8.api.ContainerAutoScaler;
import io.fabric8.api.ContainerAutoScalerFactory;
import io.fabric8.api.ContainerProvider;
import io.fabric8.api.CreateContainerMetadata;
import io.fabric8.api.CreationStateListener;
import io.fabric8.api.EnvironmentVariables;
import io.fabric8.api.FabricRequirements;
import io.fabric8.api.FabricService;
import io.fabric8.api.Profile;
import io.fabric8.api.ProfileRequirements;
import io.fabric8.api.Profiles;
import io.fabric8.api.ZkDefs;
import io.fabric8.api.jcip.ThreadSafe;
import io.fabric8.api.scr.Configurer;
import io.fabric8.api.scr.ValidatingReference;
import io.fabric8.utils.Files;
import io.fabric8.utils.Objects;
import io.fabric8.utils.Strings;
import io.fabric8.docker.api.Docker;
import io.fabric8.docker.api.DockerApiConnectionException;
import io.fabric8.docker.api.Dockers;
import io.fabric8.docker.api.container.ContainerConfig;
import io.fabric8.docker.api.container.ContainerCreateStatus;
import io.fabric8.docker.provider.DockerConstants;
import io.fabric8.docker.provider.DockerContainerProviderSupport;
import io.fabric8.docker.provider.DockerCreateOptions;
import io.fabric8.kubernetes.api.Kubernetes;
import io.fabric8.kubernetes.api.KubernetesFactory;
import io.fabric8.kubernetes.api.KubernetesHelper;
import io.fabric8.kubernetes.api.model.DesiredState;
import io.fabric8.kubernetes.api.model.ManifestContainer;
import io.fabric8.kubernetes.api.model.ManifestSchema;
import io.fabric8.kubernetes.api.model.PodSchema;
import io.fabric8.kubernetes.api.model.Port;
import io.fabric8.kubernetes.api.model.ReplicationControllerSchema;
import io.fabric8.kubernetes.api.model.ServiceSchema;
import org.apache.curator.framework.CuratorFramework;
import org.apache.felix.scr.annotations.Activate;
import org.apache.felix.scr.annotations.Component;
import org.apache.felix.scr.annotations.ConfigurationPolicy;
import org.apache.felix.scr.annotations.Deactivate;
import org.apache.felix.scr.annotations.Modified;
import org.apache.felix.scr.annotations.Properties;
import org.apache.felix.scr.annotations.Property;
import org.apache.felix.scr.annotations.Reference;
import org.apache.felix.scr.annotations.Service;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.management.InstanceNotFoundException;
import javax.management.MBeanRegistrationException;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import static io.fabric8.kubernetes.api.KubernetesHelper.getPodMap;
import static io.fabric8.kubernetes.api.KubernetesHelper.getReplicationControllerMap;
import static io.fabric8.kubernetes.api.KubernetesHelper.getServiceMap;
import static io.fabric8.kubernetes.provider.KubernetesConstants.LABELS;

/**
* A container provider using <a href="http://kubernetes.io/">Kubernetes</a> to create containers
*/
@ThreadSafe
@Component(name = "io.fabric8.kubernetes.provider",
        label = "Fabric8 Kubernetes Container Provider",
        description = "Supports managing containers on Kubernetes and OpenShift 3.x or later",
        policy = ConfigurationPolicy.OPTIONAL, immediate = true, metatype = true)
@Service(ContainerProvider.class)
@Properties(
        @Property(name = "fabric.container.protocol", value = KubernetesConstants.SCHEME)
)
public class KubernetesContainerProvider extends DockerContainerProviderSupport implements ContainerProvider<CreateKubernetesContainerOptions, CreateKubernetesContainerMetadata> {

    private static final transient Logger LOG = LoggerFactory.getLogger(KubernetesContainerProvider.class);

    @Reference(referenceInterface = FabricService.class, bind = "bindFabricService", unbind = "unbindFabricService")
    private final ValidatingReference<FabricService> fabricService = new ValidatingReference<FabricService>();
    @Reference(referenceInterface = CuratorFramework.class, bind = "bindCurator", unbind = "unbindCurator")
    private final ValidatingReference<CuratorFramework> curator = new ValidatingReference<CuratorFramework>();
    @Reference(bind = "bindConfigurer", unbind = "unbindConfigurer")
    private Configurer configurer;
    @Reference(referenceInterface = KubernetesService.class, bind = "bindKubernetesService", unbind = "unbindKubernetesService")
    private final ValidatingReference<KubernetesService> kubernetesService = new ValidatingReference<KubernetesService>();

    @Property(name = "dockerHost",
            label = "Docker Host",
            description = "The URL to connect to Docker.")
    private String dockerHost;

    private int externalPortCounter;
    private final Object portLock = new Object();

    private ObjectMapper objectMapper = KubernetesFactory.createObjectMapper();

    @Activate
    public void activate(Map<String, ?> configuration) throws Exception {
        updateConfiguration(configuration);
        activateComponent();
    }

    @Modified
    public void modified(Map<String, ?> configuration) throws Exception {
        updateConfiguration(configuration);
    }

    @Deactivate
    public void deactivate() throws MBeanRegistrationException, InstanceNotFoundException {
        deactivateComponent();
    }

    private void updateConfiguration(Map<String, ?> configuration) throws Exception {
        ClassLoader tccl = Thread.currentThread().getContextClassLoader();
        try {
            getConfigurer().configure(configuration, this);
            if (Strings.isNotBlank(dockerHost)) {
                dockerFactory.setAddress(dockerHost);
            }
            // Resteasy uses the TCCL to load the API
            Thread.currentThread().setContextClassLoader(Docker.class.getClassLoader());
            this.docker = dockerFactory.createDocker();
        } catch (Throwable e) {
            LOG.error("Failed to update configuration " + configuration + ". " + e, e);
            throw e;
        } finally {
            Thread.currentThread().setContextClassLoader(tccl);
        }
    }

    public Kubernetes getKubernetes() {
        return KubernetesService.getKubernetes(kubernetesService.getOptional());
    }

    private String getKubernetesAddress() {
        return KubernetesService.getKubernetesAddress(kubernetesService.getOptional());
    }

    public CreateKubernetesContainerOptions.Builder newBuilder() {
        return CreateKubernetesContainerOptions.builder();
    }

    @Override
    public CreateKubernetesContainerMetadata create(CreateKubernetesContainerOptions options, CreationStateListener listener) throws Exception {
        FabricService service = getFabricService();
        List<String> kubelets = getKubeletFileNames(service, options);
        if (kubelets.size() > 0) {
            return doCreateKubernetesPodsControllersServices(service, options, kubelets);
        }

        DockerCreateContainerParameters parameters = new DockerCreateContainerParameters(options).invoke();
        doCreateDockerContainer(options, parameters);

        ContainerConfig containerConfig = parameters.getContainerConfig();
        Map<String, String> environmentVariables = parameters.getEnvironmentVariables();
        String containerType = parameters.getContainerType();

        ContainerCreateStatus status = null;
        CreateKubernetesContainerMetadata metadata = null;

        metadata = createKubernetesContainerMetadata(options, status, containerType);
        publishZooKeeperValues(options, environmentVariables);
        return metadata;

    }

    protected KubernetesConfig getKubernetesConfig(FabricService service, CreateKubernetesContainerOptions options) throws Exception {
        KubernetesConfig config = null;
        Set<String> profileIds = options.getProfiles();
        String versionId = options.getVersion();
        Map<String, String> configuration = null;
        if (service != null) {
            configuration = Profiles.getOverlayConfiguration(service, profileIds, versionId,
                    KubernetesConstants.KUBERNETES_PID, "kubernetes");
        }
        if (configuration != null) {
            config = new KubernetesConfig();
            configurer.configure(configuration, config);
        }
        return config;
    }

    /**
     * Returns the file names of the kubelets in the profiles
     */
    protected List<String> getKubeletFileNames(FabricService service, CreateKubernetesContainerOptions options) throws Exception {
        Collection<Profile> profiles = Profiles.getProfiles(service, options.getProfiles(), options.getVersion());
        Set<String> allConfigFiles = Profiles.getConfigurationFileNames(profiles);
        List<String> answer = new ArrayList<>();
        for (String fileName : allConfigFiles) {
            if (fileName.startsWith("kubelet/") && fileName.endsWith(".json")) {
                answer.add(fileName);
            }
        }
        return answer;
    }

    /**
     * Loads all the kubelet objects from the profiles and returns then in a map indexed by the file name
     */
    protected Map<String, Object> loadKubelets(FabricService service, CreateKubernetesContainerOptions options, List<String> definitions, CreateKubernetesContainerMetadata metadata) {
        Map<String, Object> answer = new HashMap<>();
        String containerId = options.getName();
        byte[] json = null;
        Kubernetes kubernetes = getKubernetes();
        Objects.notNull(kubernetes, "kubernetes");

        Set<String> profileIds = options.getProfiles();
        String versionId = options.getVersion();
        List<Profile> profiles = Profiles.getProfiles(service, profileIds, versionId);

        for (String definition : definitions) {
            definition = definition.trim();
            if (!definition.contains(":")) {
                // lets assume its a file in the profile
                json = Profiles.getFileConfiguration(profiles, definition);
            }
            if (json == null) {
                URL url = null;
                try {
                    url = new URL(definition);
                } catch (MalformedURLException e) {
                    LOG.warn("Could not parse kube definition URL " + definition + ". " + e, e);
                }
                if (url != null) {
                    try {
                        InputStream in = url.openStream();
                        if (in != null) {
                            json = Files.readBytes(in);
                        }
                    } catch (IOException e) {
                        LOG.warn("Failed to load URL " + url + ". " + e, e);
                    }
                }
            }
            if (json != null) {
                Object dto = null;
                try {
                    ObjectReader reader = objectMapper.reader();
                    JsonNode tree = null;
                    if (json != null) {
                        tree = reader.readTree(new ByteArrayInputStream(json));
                        if (tree != null) {
                            JsonNode kindNode = tree.get("kind");
                            if (kindNode != null) {
                                String kind = kindNode.asText();
                                if (Objects.equal("Pod", kind)) {
                                    PodSchema podSchema = objectMapper.reader(PodSchema.class).readValue(json);
                                    configurePod(podSchema, service, options, metadata);
                                    answer.put(definition, podSchema);
                                } else if (Objects.equal("ReplicationController", kind)) {
                                    ReplicationControllerSchema replicationControllerSchema = objectMapper.reader(ReplicationControllerSchema.class).readValue(json);
                                    configureReplicationController(replicationControllerSchema, service, options, metadata);
                                    answer.put(definition, replicationControllerSchema);
                                } else if (Objects.equal("Service", kind)) {
                                    ServiceSchema serviceSchema = objectMapper.reader(ServiceSchema.class).readValue(json);
                                    configureService(serviceSchema, service, options, metadata);
                                    answer.put(definition, serviceSchema);
                                } else {
                                    LOG.warn("Unknown JSON from " + definition + ". JSON: " + tree);
                                }
                            }
                        }
                    }
                } catch (IOException e) {
                    LOG.warn("Failed to parse JSON definition: " + definition + ". " + e, e);
                }
            }
        }
        return answer;
    }

    /**
     * Creates all the controllers, pods and services from the profile metadata
     */
    protected CreateKubernetesContainerMetadata doCreateKubernetesPodsControllersServices(FabricService service, CreateKubernetesContainerOptions options, List<String> kubeletFileNames) {
        String containerId = options.getName();
        String status = "TODO";
        List<String> warnings = new ArrayList<>();
        CreateKubernetesContainerMetadata metadata = createKubernetesContainerMetadata(options, containerId, "kubelet", status, warnings);

        startKubletPodsReplicationControllersServices(service, options, kubeletFileNames, metadata);

        // TODO
        // publishZooKeeperValues(options, environmentVariables);
        return metadata;
    }

    /**
     * Starts any kublets from the profiles which are not already running
     */
    protected void startKubletPodsReplicationControllersServices(FabricService service, CreateKubernetesContainerOptions options, List<String> kubeletFileNames, CreateKubernetesContainerMetadata metadata) {
        Kubernetes kubernetes = getKubernetes();
        Objects.notNull(kubernetes, "kubernetes");

        Map<String, PodSchema> podMap = null;
        Map<String, ReplicationControllerSchema> replicationControllerMap = null;
        Map<String, ServiceSchema> serviceMap = null;

        Map<String, Object> kubelets = loadKubelets(service, options, kubeletFileNames, metadata);
        Set<Map.Entry<String, Object>> entries = kubelets.entrySet();
        for (Map.Entry<String, Object> entry : entries) {
            String definition = entry.getKey();
            Object kubelet = entry.getValue();
            if (kubelet instanceof PodSchema) {
                PodSchema podSchema = (PodSchema) kubelet;
                if (podMap == null) {
                    podMap = getPodMap(kubernetes);
                }
                String id = podSchema.getId();
                PodSchema old = podMap.get(id);
                if (isRunning(old)) {
                    LOG.info("Not creating pod for " + id + " from definition " + definition + " as its already running");
                } else {
                    LOG.info("Creating a pod from " + definition);
                    try {
                        Object answer = kubernetes.createPod(podSchema);
                        LOG.info("Created pod result: " + answer);
                    } catch (Exception e) {
                        LOG.error("Failed to create pod from " + definition + ". " + e + ". " + podSchema, e);
                    }
                }
            } else if (kubelet instanceof ReplicationControllerSchema) {
                ReplicationControllerSchema replicationControllerSchema = (ReplicationControllerSchema) kubelet;
                if (replicationControllerMap == null) {
                    replicationControllerMap = getReplicationControllerMap(kubernetes);
                }
                String id = replicationControllerSchema.getId();
                ReplicationControllerSchema old = replicationControllerMap.get(id);
                if (isRunning(old)) {
                    LOG.info("Not creating replicationController for " + id + " from definition " + definition + " as its already running");
                } else {
                    LOG.info("Creating a replicationController from " + definition);
                    try {
                        Object answer = kubernetes.createReplicationController(replicationControllerSchema);
                        LOG.info("Created replicationController: " + answer);
                    } catch (Exception e) {
                        LOG.error("Failed to create controller from " + definition + ". " + e + ". " + replicationControllerSchema, e);
                    }
                }
            } else if (kubelet instanceof ServiceSchema) {
                ServiceSchema serviceSchema = (ServiceSchema) kubelet;
                if (serviceMap == null) {
                    serviceMap = getServiceMap(kubernetes);
                }
                String id = serviceSchema.getId();
                ServiceSchema old = serviceMap.get(id);
                if (isRunning(old)) {
                    LOG.info("Not creating pod for " + id + " from defintion " + definition + " as its already running");
                } else {
                    LOG.info("Creating a service from " + definition);
                    try {
                        Object answer = kubernetes.createService(serviceSchema);
                        LOG.info("Created service: " + answer);
                    } catch (Exception e) {
                        LOG.error("Failed to create controller from " + definition + ". " + e + ". " + serviceSchema, e);
                    }
                }
            } else {
                LOG.warn("Unknown Kublelet from " + definition + ". Object: " + kubelet);
            }
        }
    }

    /**
     * Stops any kublets from the profiles
     */
    protected void stopKubletPodsReplicationControllersServices(FabricService service, CreateKubernetesContainerOptions options, List<String> kubeletFileNames, CreateKubernetesContainerMetadata metadata) {
        Kubernetes kubernetes = getKubernetes();
        Objects.notNull(kubernetes, "kubernetes");

        Map<String, PodSchema> podMap = null;
        Map<String, ReplicationControllerSchema> replicationControllerMap = null;
        Map<String, ServiceSchema> serviceMap = null;

        Map<String, Object> kubelets = loadKubelets(service, options, kubeletFileNames, metadata);
        Set<Map.Entry<String, Object>> entries = kubelets.entrySet();
        for (Map.Entry<String, Object> entry : entries) {
            String definition = entry.getKey();
            Object kubelet = entry.getValue();
            if (kubelet instanceof PodSchema) {
                PodSchema podSchema = (PodSchema) kubelet;
                if (podMap == null) {
                    podMap = getPodMap(kubernetes);
                }
                String id = podSchema.getId();
                PodSchema old = podMap.get(id);
                if (isRunning(old)) {
                    try {
                        deletePod(id);
                    } catch (Exception e) {
                        LOG.error("Failed to delete pod " + id + " from " + definition + ": " + e + ". ", e);
                    }
                }
            } else if (kubelet instanceof ReplicationControllerSchema) {
                ReplicationControllerSchema replicationControllerSchema = (ReplicationControllerSchema) kubelet;
                if (replicationControllerMap == null) {
                    replicationControllerMap = getReplicationControllerMap(kubernetes);
                }
                String id = replicationControllerSchema.getId();
                ReplicationControllerSchema old = replicationControllerMap.get(id);
                if (isRunning(old)) {
                    try {
                        deleteReplicationController(id);
                    } catch (Exception e) {
                        LOG.error("Failed to delete replicationController " + id + " from " + definition + ": " + e + ". ", e);
                    }
                }
            } else if (kubelet instanceof ServiceSchema) {
                ServiceSchema serviceSchema = (ServiceSchema) kubelet;
                if (serviceMap == null) {
                    serviceMap = getServiceMap(kubernetes);
                }
                String id = serviceSchema.getId();
                ServiceSchema old = serviceMap.get(id);
                if (isRunning(old)) {
                    try {
                        deleteService(id);
                    } catch (Exception e) {
                        LOG.error("Failed to delete service " + id + " from " + definition + ": " + e + ". ", e);
                    }
                }
            } else {
                LOG.warn("Unknown Kublelet from " + definition + ". Object: " + kubelet);
            }
        }
    }

    protected boolean isRunning(PodSchema entity) {
        // TODO we could maybe ignore failed services?
        return entity != null;
    }

    protected boolean isRunning(ReplicationControllerSchema entity) {
        // TODO we could maybe ignore failed services?
        return entity != null;
    }

    protected boolean isRunning(ServiceSchema entity) {
        // TODO we could maybe ignore failed services?
        return entity != null;
    }

    protected void configurePod(PodSchema podSchema, FabricService service, CreateKubernetesContainerOptions options, CreateKubernetesContainerMetadata metadata) {
        podSchema.setLabels(configureLabels(podSchema.getLabels(), service, options));
        String id = podSchema.getId();
        if (Strings.isNotBlank(id)) {
            metadata.addPodId(id);
        }
    }

    protected void configureReplicationController(ReplicationControllerSchema replicationControllerSchema, FabricService service, CreateKubernetesContainerOptions options, CreateKubernetesContainerMetadata metadata) {
        replicationControllerSchema.setLabels(configureLabels(replicationControllerSchema.getLabels(), service, options));
        String id = replicationControllerSchema.getId();
        if (Strings.isNotBlank(id)) {
            metadata.addReplicationControllerId(id);
        }
    }

    protected void configureService(ServiceSchema serviceSchema, FabricService service, CreateKubernetesContainerOptions options, CreateKubernetesContainerMetadata metadata) {
        serviceSchema.setLabels(configureLabels(serviceSchema.getLabels(), service, options));
        String id = serviceSchema.getId();
        if (Strings.isNotBlank(id)) {
            metadata.addServiceId(id);
        }
    }

    protected Map<String, String> configureLabels(Map<String, String> labels, FabricService service, CreateKubernetesContainerOptions options) {
        String name = options.getName();
        Set<String> profileIds = options.getProfiles();
        String versionId = options.getVersion();
        return updateLabels(labels, service, name, profileIds, versionId);
    }

    @Override
    public void start(Container container) {
        assertValid();
        CreateKubernetesContainerMetadata containerMetadata = getContainerMetadata(container);
        CreateKubernetesContainerOptions options = containerMetadata.getCreateOptions();
        if (containerMetadata != null && containerMetadata.isKubelet()) {
            try {
                FabricService service = getFabricService();
                List<String> kubelets = getKubeletFileNames(service, options);
                if (kubelets.size() > 0) {
                    startKubletPodsReplicationControllersServices(service, options, kubelets, containerMetadata);
                }
            } catch (Exception e) {
                String message = "Could not start kubelet for container: " + container.getId() + ": " + e + Dockers.dockerErrorMessage(e);
                LOG.warn(message, e);
                throw new RuntimeException(message, e);
            }
        } else {
            try {
                DockerCreateContainerParameters parameters = new DockerCreateContainerParameters(options).invoke();
                doCreateDockerContainer(options, parameters);
            } catch (Exception e) {
                String message = "Could not start pod for container: " + container.getId() + ": " + e + Dockers.dockerErrorMessage(e);
                LOG.warn(message, e);
                throw new RuntimeException(message, e);
            }
        }
    }

    @Override
    public void stop(Container container) {
        assertValid();
        CreateKubernetesContainerMetadata containerMetadata = getContainerMetadata(container);
        CreateKubernetesContainerOptions options = containerMetadata.getCreateOptions();
        if (containerMetadata != null && containerMetadata.isKubelet()) {
            try {
                FabricService service = getFabricService();
                List<String> kubelets = getKubeletFileNames(service, options);
                if (kubelets.size() > 0) {
                    stopKubletPodsReplicationControllersServices(service, options, kubelets, containerMetadata);
                }
            } catch (Exception e) {
                String message = "Could not start kubelet for container: " + container.getId() + ": " + e + Dockers.dockerErrorMessage(e);
                LOG.warn(message, e);
                throw new RuntimeException(message, e);
            }
        } else {
            String id = getPodId(container);
            if (!Strings.isNullOrBlank(id)) {
                try {
                    deletePod(id);
                } catch (Exception e) {
                    String message = "Could not remove pod: it probably no longer exists " + e + Dockers.dockerErrorMessage(e);
                    LOG.warn(message, e);
                    throw new RuntimeException(message, e);
                }
                container.setProvisionResult(Container.PROVISION_STOPPED);
            }
        }
    }


    protected void doCreateDockerContainer(CreateKubernetesContainerOptions options, DockerCreateContainerParameters parameters) throws Exception {
        Kubernetes kubernetes = getKubernetes();
        Objects.notNull(kubernetes, "kubernetes");
        ContainerConfig containerConfig = parameters.getContainerConfig();
        Map<String, String> environmentVariables = parameters.getEnvironmentVariables();
        environmentVariables.put(EnvironmentVariables.FABRIC8_LISTEN_ADDRESS, "0.0.0.0");
        //environmentVariables.put(EnvironmentVariables.FABRIC8_FABRIC_ENVIRONMENT, "kubernetes");
        environmentVariables.remove(EnvironmentVariables.FABRIC8_GLOBAL_RESOLVER);
        environmentVariables.remove(EnvironmentVariables.FABRIC8_MANUALIP);
        String containerType = parameters.getContainerType();
        String jolokiaUrl = parameters.getJolokiaUrl();
        String name = options.getName();
        String image = containerConfig.getImage();
        Set<String> profileIds = options.getProfiles();
        String versionId = options.getVersion();
        FabricService service = getFabricService();

        PodSchema pod = new PodSchema();
        pod.setId(KubernetesHelpers.containerNameToPodId(name));

        Map<String, String> labels = updateLabels(null, service, name, profileIds, versionId);

        pod.setLabels(labels);
        DesiredState desiredState = new DesiredState();
        pod.setDesiredState(desiredState);
        ManifestSchema manifest = new ManifestSchema();
        manifest.setVersion(ManifestSchema.Version.V_1_BETA_1);
        desiredState.setManifest(manifest);

        ManifestContainer manifestContainer = new ManifestContainer();
        manifestContainer.setName(name);
        manifestContainer.setImage(image);
        List<String> cmd = options.getCmd();
        if (cmd != null && !cmd.isEmpty()) {
            manifestContainer.setCommand(cmd);
        }
        manifestContainer.setWorkingDir(options.getWorkingDir());
        manifestContainer.setEnv(KubernetesHelper.createEnv(environmentVariables));

        // TODO
        //manifestContainer.setVolumeMounts();

        Map<String, String> portConfigurations = Profiles.getOverlayConfiguration(service, profileIds, versionId, Constants.PORTS_PID, "kubernetes");
        if (portConfigurations != null && portConfigurations.size() > 0) {
            List<Port> ports = new ArrayList<>();
            Set<Map.Entry<String, String>> entries = portConfigurations.entrySet();
            for (Map.Entry<String, String> entry : entries) {
                String portName = entry.getKey();
                String defaultPortValue = entry.getValue();
                if (Strings.isNotBlank(defaultPortValue)) {
                    Integer portNumber = null;
                    try {
                        portNumber = Integer.parseInt(defaultPortValue);
                    } catch (NumberFormatException e) {
                        LOG.warn("Could not parse '" + defaultPortValue
                                + "' as integer for port " + portName
                                + " for profiles " + profileIds + " " + versionId + ". " + e, e);
                    }
                    String hostPortText = environmentVariables.get("FABRIC8_" + portName + "_PROXY_PORT");
                    Integer hostPort = null;
                    if (hostPortText != null) {
                        try {
                            hostPort = Integer.parseInt(hostPortText);
                        } catch (NumberFormatException e) {
                            LOG.warn("Could not parse '" + hostPortText
                                    + "' as integer for port " + portName
                                    + " for profiles " + profileIds + " " + versionId + ". " + e, e);
                        }
                    }
                    if (portNumber != null && hostPort != null) {
                        Port port = new Port();
                        //port.setName(portName);
                        //port.setProtocol(portName.toLowerCase());
                        //port.setProtocol("tcp");
                        port.setContainerPort(portNumber);
                        port.setHostPort(hostPort);
                        ports.add(port);
                    }
                }
            }
            manifestContainer.setPorts(ports);
        }

        List<ManifestContainer> containers = new ArrayList<>();
        containers.add(manifestContainer);
        manifest.setContainers(containers);

        try {
            LOG.info("About to create pod with image " + image + " on " + getKubernetesAddress() + " with " + pod);
            Object answer = kubernetes.createPod(pod);
            LOG.info("Go answer: " + answer);
        } catch (Exception e) {
            LOG.info("Failed to create pod " + name + " from config " + pod
                    + ": " + e + Dockers.dockerErrorMessage(e), e);
            throw e;
        }
    }

    protected Map<String, String> updateLabels(Map<String, String> initialLabels, FabricService service, String containerName, Set<String> profileIds, String versionId) {
        Map<String, String> labels = new HashMap<>();
        if (initialLabels != null) {
            labels.putAll(initialLabels);
        }
        if (!labels.containsKey(LABELS.FABRIC8)) {
            labels.put(LABELS.FABRIC8, "true");
        }
        if (!labels.containsKey(LABELS.NAME)) {
            labels.put(LABELS.NAME, containerName);
        }
        if (!labels.containsKey(LABELS.PROFILE)) {
            String profileString = Strings.join(profileIds, ",");
            labels.put(LABELS.PROFILE, profileString);
        }
        if (!labels.containsKey(LABELS.VERSION)) {
            labels.put(LABELS.VERSION, versionId);
        }
        Map<String, String> labelConfiguration = Profiles.getOverlayConfiguration(service, profileIds, versionId, KubernetesConstants.LABELS_PID, "kubernetes");
        if (labelConfiguration != null) {
            labels.putAll(labelConfiguration);
        }
        return labels;
    }


    public static CreateKubernetesContainerMetadata createKubernetesContainerMetadata(CreateKubernetesContainerOptions options, ContainerCreateStatus status, String containerType) {
        String containerId = options.getName();
        List<String> warnings = new ArrayList<String>();
        String statusId = "unknown";
        if (status != null) {
            statusId = status.getId();
            String[] warningArray = status.getWarnings();
            if (warningArray != null) {
                Collections.addAll(warnings, warningArray);
            }
        }
        return createKubernetesContainerMetadata(options, containerId, containerType, statusId, warnings);
    }

    public static CreateKubernetesContainerMetadata createKubernetesContainerMetadata(CreateKubernetesContainerOptions options, String containerId, String containerType, String statusId, List<String> warnings) {
        CreateKubernetesContainerMetadata metadata = new CreateKubernetesContainerMetadata(statusId, warnings);
        metadata.setFailure(null);
        metadata.setCreateOptions(options);
        metadata.setContainerName(containerId);
        metadata.setContainerType(containerType);
        metadata.setOverridenResolver(ZkDefs.MANUAL_IP);
        return metadata;
    }


    @Override
    protected int createExternalPort(String containerId, String portKey, Set<Integer> usedPortByHost, DockerCreateOptions options) {
        synchronized (portLock) {
            while (true) {
                if (externalPortCounter <= 0) {
                    externalPortCounter = options.getMinimumPort();
                    if (externalPortCounter == 0) {
                        externalPortCounter = DockerConstants.DEFAULT_EXTERNAL_PORT;
                    }
                } else {
                    externalPortCounter++;
                }
                if (!usedPortByHost.contains(externalPortCounter)) {
                    Container container = getFabricService().getCurrentContainer();
                    String pid = Constants.PORTS_PID;
                    String key = containerId + "-" + portKey;
                    getFabricService().getPortService().registerPort(container, pid, key, externalPortCounter);
                    return externalPortCounter;
                }
            }
        }
    }

    @Override
    protected Set<Integer> findUsedPortByHostAndDocker() {
        try {
            // TODO
            return new HashSet<>();
        } catch (DockerApiConnectionException e) {
            String suggestion = String.format("Can't connect to the Docker server. Are you sure a Docker server is running at %s?", dockerFactory.getAddress());
            throw new DockerApiConnectionException(suggestion, e.getCause());
        }
    }

    protected void deletePod(String id) throws Exception {
        LOG.info("stopping pod " + id);
        Kubernetes kubernetes = getKubernetes();
        Objects.notNull(kubernetes, "kubernetes");
        kubernetes.deletePod(id);
    }

    protected void deleteReplicationController(String id) throws Exception {
        LOG.info("stopping replicationController " + id);
        Kubernetes kubernetes = getKubernetes();
        Objects.notNull(kubernetes, "kubernetes");
        kubernetes.deleteReplicationController(id);
    }

    protected void deleteService(String id) throws Exception {
        LOG.info("stopping service " + id);
        Kubernetes kubernetes = getKubernetes();
        Objects.notNull(kubernetes, "kubernetes");
        kubernetes.deleteService(id);
    }

    @Override
    public void destroy(Container container) {
        assertValid();
        String id = getPodId(container);
        if (!Strings.isNullOrBlank(id)) {
            try {
                deletePod(id);
            } catch (Exception e) {
                LOG.info("Could not remove pod: it probably no longer exists " + e + Dockers.dockerErrorMessage(e), e);
            }
        }
    }

    @Override
    public String getScheme() {
        assertValid();
        return KubernetesConstants.SCHEME;
    }

    @Override
    public boolean isValidProvider() {
        return true;
    }

    @Override
    public Class<CreateKubernetesContainerOptions> getOptionsType() {
        assertValid();
        return CreateKubernetesContainerOptions.class;
    }

    @Override
    public Class<CreateKubernetesContainerMetadata> getMetadataType() {
        assertValid();
        return CreateKubernetesContainerMetadata.class;
    }

    public Docker getDocker() {
        return docker;
    }

    protected String getPodId(Container container) {
        return KubernetesHelpers.containerNameToPodId(container.getId());
    }

    protected static CreateKubernetesContainerMetadata getContainerMetadata(Container container) {
        CreateContainerMetadata<?> value = container.getMetadata();
        if (value instanceof CreateKubernetesContainerMetadata) {
            return (CreateKubernetesContainerMetadata) value;
        } else {
            return null;
        }
    }

    protected FabricService getFabricService() {
        return fabricService.get();
    }

    protected CuratorFramework getCuratorFramework() {
        return curator.getOptional();
    }

    public Configurer getConfigurer() {
        return configurer;
    }

    public void setConfigurer(Configurer configurer) {
        this.configurer = configurer;
    }

    void bindFabricService(FabricService fabricService) {
        this.fabricService.bind(fabricService);
    }

    void unbindFabricService(FabricService fabricService) {
        this.fabricService.unbind(fabricService);
    }

    void bindCurator(CuratorFramework curator) {
        this.curator.bind(curator);
        // TODO
        // zkMasterCache = new ZooKeeperMasterCache(curator);
    }

    void unbindCurator(CuratorFramework curator) {
        this.curator.unbind(curator);
    }

    void bindKubernetesService(KubernetesService kubernetesService) {
        this.kubernetesService.bind(kubernetesService);
    }

    void unbindKubernetesService(KubernetesService kubernetesService) {
        this.kubernetesService.unbind(kubernetesService);
    }

    void bindConfigurer(Configurer configurer) {
        this.setConfigurer(configurer);
    }

    void unbindConfigurer(Configurer configurer) {
        this.setConfigurer(null);
    }

    @Override
    public String getDockerAddress() {
        return dockerFactory.getAddress();
    }

}
TOP

Related Classes of io.fabric8.kubernetes.provider.KubernetesContainerProvider

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.