Package io.fabric8.docker.provider

Source Code of io.fabric8.docker.provider.DockerContainerProviderSupport

/**
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements.  See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License.  You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.fabric8.docker.provider;

import io.fabric8.api.Constants;
import io.fabric8.api.Container;
import io.fabric8.api.EnvironmentVariables;
import io.fabric8.api.FabricService;
import io.fabric8.api.Profile;
import io.fabric8.api.ProfileService;
import io.fabric8.api.Profiles;
import io.fabric8.api.Version;
import io.fabric8.api.ZkDefs;
import io.fabric8.api.scr.AbstractComponent;
import io.fabric8.api.scr.Configurer;
import io.fabric8.utils.Strings;
import io.fabric8.container.process.JavaContainerConfig;
import io.fabric8.container.process.JolokiaAgentHelper;
import io.fabric8.container.process.ZooKeeperPublishConfig;
import io.fabric8.docker.api.Auth;
import io.fabric8.docker.api.Docker;
import io.fabric8.docker.api.DockerFactory;
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.customizer.CustomDockerContainerImageBuilder;
import io.fabric8.docker.provider.customizer.CustomDockerContainerImageOptions;
import io.fabric8.service.child.ChildContainers;
import org.apache.curator.framework.CuratorFramework;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.SortedMap;
import java.util.TreeMap;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
* Base class for docker centric docker container providers
*/
public abstract class DockerContainerProviderSupport extends AbstractComponent {
    private static final transient Logger LOG = LoggerFactory.getLogger(DockerContainerProviderSupport.class);


    private final ExecutorService downloadExecutor = Executors.newSingleThreadExecutor();
    protected DockerFactory dockerFactory = new DockerFactory();
    protected Docker docker;

    protected abstract FabricService getFabricService();

    protected abstract CuratorFramework getCuratorFramework();

    protected abstract Configurer getConfigurer();

    protected abstract int createExternalPort(String containerId, String portKey, Set<Integer> usedPortByHost, DockerCreateOptions options);

    protected abstract Set<Integer> findUsedPortByHostAndDocker();

    public abstract String getDockerAddress();

    protected DockerProviderConfig createDockerProviderConfig(Map<String, String> dockerProviderConfig, Map<String, String> environmentVariables) throws Exception {
        FabricService service = getFabricService();
        JolokiaAgentHelper.substituteEnvironmentVariableExpressions(dockerProviderConfig, environmentVariables, service, getCuratorFramework());
        return createDockerProviderConfig(dockerProviderConfig);
    }

    protected DockerProviderConfig createDockerProviderConfig(Map<String, String> dockerProviderConfig) throws Exception {
        DockerProviderConfig dockerProviderConfigObject = new DockerProviderConfig();
        getConfigurer().configure(dockerProviderConfig, dockerProviderConfigObject);
        return dockerProviderConfigObject;
    }


    protected void publishZooKeeperValues(DockerCreateOptions options, Map<String, String> environmentVariables) {
        Map<String, Map<String, String>> publishConfigurations = Profiles.getOverlayFactoryConfigurations(getFabricService(), options.getProfiles(), options.getVersion(), ZooKeeperPublishConfig.PROCESS_CONTAINER_ZK_PUBLISH_PID);
        Set<Map.Entry<String, Map<String, String>>> entries = publishConfigurations.entrySet();
        for (Map.Entry<String, Map<String, String>> entry : entries) {
            String configName = entry.getKey();
            Map<String, String> exportConfig = entry.getValue();

            CuratorFramework curatorFramework = getCuratorFramework();
            if (exportConfig != null && !exportConfig.isEmpty() && curatorFramework != null) {
                JolokiaAgentHelper.substituteEnvironmentVariableExpressions(exportConfig, environmentVariables, getFabricService(), curatorFramework, true);
                ZooKeeperPublishConfig config = new ZooKeeperPublishConfig();
                try {
                    getConfigurer().configure(exportConfig, config);
                    config.publish(curatorFramework, null, null, null, environmentVariables);
                } catch (Exception e) {
                    LOG.warn("Failed to publish configuration " + configName + " of " + config + " due to: " + e, e);
                }
            }
        }
    }

    public static CreateDockerContainerMetadata newInstance(ContainerConfig containerConfig, DockerCreateOptions options, ContainerCreateStatus status, String containerType) {
        List<String> warnings = new ArrayList<String>();
        String[] warningArray = status.getWarnings();
        if (warningArray != null) {
            Collections.addAll(warnings, warningArray);
        }
        CreateDockerContainerMetadata metadata = new CreateDockerContainerMetadata(status.getId(), warnings);
        String containerId = options.getName();
        metadata.setContainerName(containerId);
        metadata.setContainerType(containerType);
        metadata.setOverridenResolver(ZkDefs.MANUAL_IP);
        metadata.setCreateOptions(options);
        return metadata;
    }

    protected ContainerConfig createContainerConfig(DockerCreateOptions options) {
        ContainerConfig containerConfig = new ContainerConfig();
        containerConfig.setImage(options.getImage());
        List<String> cmdList = options.getCmd();
        if (cmdList != null && cmdList.size() > 0) {
            containerConfig.setCmd(cmdList.toArray(new String[cmdList.size()]));
        }
        containerConfig.setEntrypoint(options.getEntrypoint());
        String workingDir = options.getWorkingDir();
        if (workingDir != null) {
            containerConfig.setWorkingDir(workingDir);
        }
        containerConfig.setAttachStdout(true);
        containerConfig.setAttachStderr(true);
        containerConfig.setTty(true);
        return containerConfig;
    }


    public class DockerCreateContainerParameters {
        private DockerCreateOptions options;
        private ContainerConfig containerConfig;
        private Map<String, String> environmentVariables;
        private String containerType;
        private String jolokiaUrl;

        public DockerCreateContainerParameters(DockerCreateOptions options) throws Exception {
            this.options = options;
        }

        public ContainerConfig getContainerConfig() {
            return containerConfig;
        }

        public Map<String, String> getEnvironmentVariables() {
            return environmentVariables;
        }

        public String getContainerType() {
            return containerType;
        }

        public String getJolokiaUrl() {
            return jolokiaUrl;
        }

        public DockerCreateContainerParameters invoke() throws Exception {
            assertValid();

            String containerId = options.getName();
            containerConfig = createContainerConfig(options);

            // allow values to be extracted from the profile configuration
            // such as the image
            Set<String> profileIds = options.getProfiles();
            String versionId = options.getVersion();
            FabricService service = getFabricService();
            Map<String, String> configOverlay = new HashMap<>();
            Map<String, String> ports = null;
            Map<String, String> dockerProviderConfig = new HashMap<>();

            List<Profile> profileOverlays = new ArrayList<>();
            Version version = null;
            if (profileIds != null && versionId != null) {
                ProfileService profileService = service.adapt(ProfileService.class);
                version = profileService.getVersion(versionId);
                if (version != null) {
                    for (String profileId : profileIds) {
                        Profile profile = version.getRequiredProfile(profileId);
                        if (profile != null) {
                            Profile overlay = profileService.getOverlayProfile(profile);
                            profileOverlays.add(overlay);
                            Map<String, String> dockerConfig = overlay.getConfiguration(DockerConstants.DOCKER_PROVIDER_PID);
                            if (dockerConfig != null) {
                                configOverlay.putAll(dockerConfig);
                            }
                            if (ports == null || ports.size() == 0) {
                                ports = overlay.getConfiguration(Constants.PORTS_PID);
                            }
                        }
                    }
                    if (version.hasProfile(DockerConstants.DOCKER_PROVIDER_PROFILE_ID)) {
                        Profile profile = version.getRequiredProfile(DockerConstants.DOCKER_PROVIDER_PROFILE_ID);
                        if (profile != null) {
                            Profile overlay = profileService.getOverlayProfile(profile);
                            Map<String, String> dockerConfig = overlay.getConfiguration(DockerConstants.DOCKER_PROVIDER_PID);
                            if (dockerConfig != null) {
                                dockerProviderConfig.putAll(dockerConfig);
                            }
                        }
                    }
                }
            }
            if (ports == null || ports.size() == 0) {
                // lets find the defaults from the docker profile
                if (version == null) {
                    version = service.getRequiredDefaultVersion();
                }
                Profile dockerProfile = version.getRequiredProfile("docker");
                ports = dockerProfile.getConfiguration(Constants.PORTS_PID);
                if (ports == null || ports.size() == 0) {
                    LOG.warn("Could not a docker ports configuration for: " + Constants.PORTS_PID);
                    ports = new HashMap<String, String>();
                }
            }
            LOG.info("Got port configuration: " + ports);

            environmentVariables = ChildContainers.getEnvironmentVariables(service, options, DockerConstants.SCHEME);

            DockerProviderConfig configOverlayDockerProvider = createDockerProviderConfig(configOverlay, environmentVariables);

            CuratorFramework curatorOptional = getCuratorFramework();
            String image = JolokiaAgentHelper.substituteVariableExpression(containerConfig.getImage(), environmentVariables, service, curatorOptional, true);

            if (Strings.isNullOrBlank(image)) {
                image = configOverlayDockerProvider.getImage();
                if (Strings.isNullOrBlank(image)) {
                    DockerProviderConfig dockerProviderConfigObject = createDockerProviderConfig(dockerProviderConfig, environmentVariables);
                    image = dockerProviderConfigObject.getImage();
                }
                if (Strings.isNullOrBlank(image)) {
                    image = System.getenv(DockerConstants.EnvironmentVariables.FABRIC8_DOCKER_DEFAULT_IMAGE);
                }
                if (Strings.isNullOrBlank(image)) {
                    image = DockerConstants.DEFAULT_IMAGE;
                }
                containerConfig.setImage(image);
            }
            containerType = "docker " + image;
            Container container = service.getContainer(containerId);
            if (container != null) {
                container.setType(containerType);
            }


            String[] cmd = containerConfig.getCmd();
            if (cmd == null || cmd.length == 0) {
                String value = configOverlayDockerProvider.getCmd();
                if (Strings.isNullOrBlank(value)) {
                    cmd = null;
                } else {
                    cmd = new String[]{value};
                }
                containerConfig.setCmd(cmd);
            }

            Map<String, Integer> internalPorts = options.getInternalPorts();
            Map<String, Integer> externalPorts = options.getExternalPorts();

            Map<String, Object> exposedPorts = new HashMap<>();
            Set<Integer> usedPortByHost = findUsedPortByHostAndDocker();
            Map<String, String> emptyMap = new HashMap<>();

            SortedMap<Integer, String> sortedInternalPorts = new TreeMap<>();
            for (Map.Entry<String, String> portEntry : ports.entrySet()) {
                String portName = portEntry.getKey();
                String portText = portEntry.getValue();
                if (portText != null && !Strings.isNullOrBlank(portText)) {
                    Integer port = null;
                    try {
                        port = Integer.parseInt(portText);
                    } catch (NumberFormatException e) {
                        LOG.warn("Ignoring bad port number for " + portName + " value '" + portText + "' in PID: " + Constants.PORTS_PID);
                    }
                    if (port != null) {
                        sortedInternalPorts.put(port, portName);
                        internalPorts.put(portName, port);
                        exposedPorts.put(portText + "/tcp", emptyMap);
                    } else {
                        LOG.info("No port for " + portName);
                    }
                }
            }

            String dockerHost = dockerFactory.getDockerHost();
            jolokiaUrl = null;

            Map<String, String> javaContainerConfig = Profiles.getOverlayConfiguration(service, profileIds, versionId, Constants.JAVA_CONTAINER_PID);
            JavaContainerConfig javaConfig = new JavaContainerConfig();
            getConfigurer().configure(javaContainerConfig, javaConfig);

            boolean isJavaContainer = ChildContainers.isJavaContainer(getFabricService(), options);

            // lets create the ports in sorted order
            for (Map.Entry<Integer, String> entry : sortedInternalPorts.entrySet()) {
                Integer port = entry.getKey();
                String portName = entry.getValue();
                int externalPort = createExternalPort(containerId, portName, usedPortByHost, options);
                externalPorts.put(portName, externalPort);
                environmentVariables.put("FABRIC8_" + portName + "_PORT", "" + port);
                environmentVariables.put("FABRIC8_" + portName + "_PROXY_PORT", "" + externalPort);

                if (portName.equals(JolokiaAgentHelper.JOLOKIA_PORT_NAME)) {
                    jolokiaUrl = "http://" + dockerHost + ":" + externalPort + "/jolokia/";
                    LOG.info("Found Jolokia URL: " + jolokiaUrl);

                    JolokiaAgentHelper.substituteEnvironmentVariables(javaConfig, environmentVariables, isJavaContainer, JolokiaAgentHelper.getJolokiaPortOverride(port), JolokiaAgentHelper.getJolokiaAgentIdOverride(getFabricService().getEnvironment()));
                } else {
                    JolokiaAgentHelper.substituteEnvironmentVariables(javaConfig, environmentVariables, isJavaContainer, JolokiaAgentHelper.getJolokiaAgentIdOverride(getFabricService().getEnvironment()));

                }
            }
            javaConfig.updateEnvironmentVariables(environmentVariables, isJavaContainer);


            LOG.info("Passing in manual ip: " + dockerHost);
            environmentVariables.put(EnvironmentVariables.FABRIC8_MANUALIP, dockerHost);
            if (container != null) {
                container.setManualIp(dockerHost);
            }
            if (!environmentVariables.containsKey(EnvironmentVariables.FABRIC8_LISTEN_ADDRESS)) {
                environmentVariables.put(EnvironmentVariables.FABRIC8_LISTEN_ADDRESS, dockerHost);
            }
            environmentVariables.put(EnvironmentVariables.FABRIC8_GLOBAL_RESOLVER, ZkDefs.MANUAL_IP);
            environmentVariables.put(EnvironmentVariables.FABRIC8_FABRIC_ENVIRONMENT, DockerConstants.SCHEME);

            // now the environment variables are all set lets see if we need to make a custom image
            String libDir = configOverlayDockerProvider.getJavaLibraryPath();
            String deployDir = configOverlayDockerProvider.getJavaDeployPath();
            String homeDir = configOverlayDockerProvider.getHomePath();
            if (Strings.isNotBlank(libDir) || Strings.isNotBlank(deployDir)) {
                if (container != null) {
                    container.setProvisionResult("preparing");
                    container.setAlive(true);
                }
                String imageRepository = configOverlayDockerProvider.getImageRepository();
                String entryPoint = configOverlayDockerProvider.getImageEntryPoint();
                List<String> names = new ArrayList<String>(profileIds);
                names.add(versionId);
                String newImageName = "fabric8-" + Strings.join(names, "-").replace('.', '-');
                String customImageUserName = configOverlayDockerProvider.getCustomImageUserName();

                DockerProviderConfig currentContainerDockerProviderConfig = null;
                Container currentContainer = service.getCurrentContainer();
                if (currentContainer != null) {
                    Map<String, String> configuration = currentContainer.getOverlayProfile().getConfiguration(DockerConstants.DOCKER_PROVIDER_PID);
                    if (configuration != null && !configuration.isEmpty()) {
                        Map<String, Map<String, String>> configurations = new HashMap<>();
                        configurations.put(DockerConstants.DOCKER_PROVIDER_PID, configuration);
                        service.substituteConfigurations(configurations);
                        configuration = configurations.get(DockerConstants.DOCKER_PROVIDER_PID);
                        configuration = JolokiaAgentHelper.substituteEnvironmentVariableExpressionKeysAndValues(configuration, System.getenv());
                        currentContainerDockerProviderConfig = createDockerProviderConfig(configuration);
                    }
                }
                if (Strings.isNullOrBlank(customImageUserName) && currentContainerDockerProviderConfig != null) {
                    customImageUserName = currentContainerDockerProviderConfig.getCustomImageUserName();
                }
                Boolean customImagePushValue = configOverlayDockerProvider.getCustomImagePush();
                if (customImagePushValue == null && currentContainerDockerProviderConfig != null) {
                    customImagePushValue = currentContainerDockerProviderConfig.getCustomImagePush();
                }
                boolean customImagePush = customImagePushValue != null && customImagePushValue.booleanValue();
                if (Strings.isNotBlank(customImageUserName)) {
                    newImageName = customImageUserName + "/" + newImageName;
                } else {
                    customImagePush = false;
                }

                CustomDockerContainerImageBuilder builder = new CustomDockerContainerImageBuilder();
                CustomDockerContainerImageOptions customDockerContainerImageOptions = new CustomDockerContainerImageOptions(image, imageRepository, newImageName, libDir, deployDir, homeDir, entryPoint, configOverlayDockerProvider.getOverlayFolder(), configOverlayDockerProvider.isMavenJavaLibraryPathLayout());

                String actualImage = builder.generateContainerImage(service, container, profileOverlays, docker, customDockerContainerImageOptions, options, downloadExecutor, environmentVariables);
                if (actualImage != null) {
                    containerConfig.setImage(actualImage);

                    if (customImagePush) {
                        LOG.info("Pushing image to repository " + newImageName + " actualImage: " + actualImage);
                        Auth authConfig = new Auth();
                        authConfig.setEmail("person@fabric8.io");
                        authConfig.setUsername(service.getZooKeeperUser());
                        authConfig.setPassword(service.getZookeeperPassword());
                        try {
                            docker.imagePush(newImageName, "latest", authConfig);
                            LOG.info("Image pushed to repository " + newImageName);
                        } catch (Exception e) {
                            LOG.info("Failed to push image " + newImageName + ": " + e + Dockers.dockerErrorMessage(e), e);
                            throw e;
                        }
                    }
                }
            }

            JolokiaAgentHelper.substituteEnvironmentVariableExpressions(environmentVariables, environmentVariables, service, curatorOptional, false);

            List<String> env = containerConfig.getEnv();
            if (env == null) {
                env = new ArrayList<>();
            }
            Dockers.addEnvironmentVariablesToList(env, environmentVariables);
            containerConfig.setExposedPorts(exposedPorts);
            containerConfig.setEnv(env);

            String name = options.getName();

            LOG.info("Creating container on docker: " + getDockerAddress() + " name: " + name + " env vars: " + env);
            LOG.info("Creating container with config: " + containerConfig);
            return this;
        }
    }
}
TOP

Related Classes of io.fabric8.docker.provider.DockerContainerProviderSupport

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.