All Downloads are FREE. Search and download functionalities are using the official Maven repository.

io.fabric8.maven.docker.service.ContainerTracker Maven / Gradle / Ivy

There is a newer version: 0.45.0
Show newest version
package io.fabric8.maven.docker.service;

import java.util.*;

import io.fabric8.maven.docker.config.ImageConfiguration;
import io.fabric8.maven.docker.config.RunImageConfiguration;
import io.fabric8.maven.docker.config.StopMode;
import io.fabric8.maven.docker.config.WaitConfiguration;
import io.fabric8.maven.docker.util.GavLabel;

/**
 * Tracker class for tracking started containers so that they can be shut down at the end when
 * docker:start and docker:stop are used in the same run
 */
public class ContainerTracker {

    // Map holding associations between started containers and their images via name and aliases
    // Key: Image, Value: Container
    private final Map imageToContainerMap = new HashMap<>();

    // Key: Alias, Value: container
    private final Map aliasToContainerMap = new HashMap<>();

    // Maps holding actions to be used when doing a shutdown
    private final Map shutdownDescriptorPerContainerMap = new LinkedHashMap<>();
    private final Map> shutdownDescriptorPerPomLabelMap = new HashMap<>();

    /**
     * Register a started container to this tracker
     *
     * @param containerId container id to register
     * @param imageConfig configuration of associated image
     * @param gavLabel pom label to identifying the reactor project where the container was created
     */
    public synchronized void registerContainer(String containerId,
                                               ImageConfiguration imageConfig,
                                               GavLabel gavLabel) {
        ContainerShutdownDescriptor descriptor = new ContainerShutdownDescriptor(imageConfig, containerId);
        shutdownDescriptorPerContainerMap.put(containerId, descriptor);
        updatePomLabelMap(gavLabel, descriptor);
        updateImageToContainerMapping(imageConfig, containerId);
    }

    /**
     * Remove a container from this container (if stored) and return its descriptor
     *
     * @param containerId id to remove
     * @return descriptor of the container removed or null
     */
    public synchronized ContainerShutdownDescriptor removeContainer(String containerId) {
        ContainerShutdownDescriptor descriptor = shutdownDescriptorPerContainerMap.remove(containerId);
        if (descriptor != null) {
            removeContainerIdFromLookupMaps(containerId);
            removeDescriptorFromPomLabelMap(descriptor);
        }
        return descriptor;
    }

    /**
     * Lookup a container by name or alias from the tracked containers
     *
     * @param lookup name or alias of the container to lookup
     * @return container id found or null
     */
    public synchronized String lookupContainer(String lookup) {
        if (aliasToContainerMap.containsKey(lookup)) {
            return aliasToContainerMap.get(lookup);
        }
        return imageToContainerMap.get(lookup);
    }

    /**
     * Get all shutdown descriptors for a given pom label and remove it from the tracker. The descriptors
     * are returned in reverse order of their registration.
     *
     * If no pom label is given, then all descriptors are returned.
     *
     * @param gavLabel the label for which to get the descriptors or null for all descriptors
     * @return the descriptors for the given label or an empty collection
     */
    public synchronized Collection removeShutdownDescriptors(GavLabel gavLabel) {
        List descriptors;
        if (gavLabel != null) {
            descriptors = removeFromPomLabelMap(gavLabel);
            removeFromPerContainerMap(descriptors);
        } else {
            // All entries are requested
            descriptors = new ArrayList<>(shutdownDescriptorPerContainerMap.values());
            clearAllMaps();
        }

        Collections.reverse(descriptors);
        return descriptors;
    }

    /**
     * Get all shutdown descriptors for a given pom label.
     * The descriptors are returned in order of their registration.
     * If no pom label is given, then all descriptors are returned.
     *
     * @param gavLabel the label for which to get the descriptors or null for all descriptors
     * @return the descriptors for the given label or an empty collection
     */
    public synchronized List getShutdownDescriptors(GavLabel gavLabel) {
        if (gavLabel == null) {
            // All entries are requested
            return new ArrayList<>(shutdownDescriptorPerContainerMap.values());
        }
        return getFromPomLabelMap(gavLabel);
    }

    // ========================================================

    private void updatePomLabelMap(GavLabel gavLabel, ContainerShutdownDescriptor descriptor) {
        if (gavLabel != null) {
            List descList = shutdownDescriptorPerPomLabelMap.get(gavLabel);
            if (descList == null) {
                descList = new ArrayList<>();
                shutdownDescriptorPerPomLabelMap.put(gavLabel, descList);
            }
            descList.add(descriptor);
        }
    }

    private void removeDescriptorFromPomLabelMap(ContainerShutdownDescriptor descriptor) {
        Iterator>> mapIt = shutdownDescriptorPerPomLabelMap.entrySet().iterator();
        while(mapIt.hasNext()) {
            Map.Entry> mapEntry = mapIt.next();
            List descs = mapEntry.getValue();
            Iterator it = descs.iterator();
            while (it.hasNext()) {
                ContainerShutdownDescriptor desc = it.next();
                if (descriptor.equals(desc)) {
                    it.remove();
                }
            }
            if (descs.size() == 0) {
                mapIt.remove();
            }
        }
    }

    private void removeContainerIdFromLookupMaps(String containerId) {
        removeValueFromMap(imageToContainerMap,containerId);
        removeValueFromMap(aliasToContainerMap,containerId);
    }

    private void removeValueFromMap(Map map, String value) {
        Iterator> it = map.entrySet().iterator();
        while (it.hasNext()) {
            Map.Entry entry = it.next();
            if (entry.getValue().equals(value)) {
                it.remove();
            }
        }
    }

    private void updateImageToContainerMapping(ImageConfiguration imageConfig, String id) {
        // Register name -> containerId and alias -> name
        imageToContainerMap.put(imageConfig.getName(), id);
        if (imageConfig.getAlias() != null) {
            aliasToContainerMap.put(imageConfig.getAlias(), id);
        }
    }

    private void removeFromPerContainerMap(List descriptors) {
        Iterator> it = shutdownDescriptorPerContainerMap.entrySet().iterator();
        while (it.hasNext()) {
            Map.Entry entry = it.next();
            if (descriptors.contains(entry.getValue())) {
                removeContainerIdFromLookupMaps(entry.getKey());
                it.remove();
            }
        }
    }

    private List removeFromPomLabelMap(GavLabel gavLabel) {
        List descriptors;
        descriptors = shutdownDescriptorPerPomLabelMap.remove(gavLabel);
        if (descriptors == null) {
            descriptors = new ArrayList<>();
        } return descriptors;
    }

    private List getFromPomLabelMap(GavLabel gavLabel) {
        List descriptors = shutdownDescriptorPerPomLabelMap.get(gavLabel);
        if (descriptors == null) {
            return new ArrayList<>();
        }
        return new ArrayList<>(descriptors);
    }

    private void clearAllMaps() {
        shutdownDescriptorPerContainerMap.clear();
        shutdownDescriptorPerPomLabelMap.clear();
        imageToContainerMap.clear();
        aliasToContainerMap.clear();
    }

    // =======================================================

    static class ContainerShutdownDescriptor {

        // The image's configuration
        private final ImageConfiguration imageConfig;

        // Alias of the image
        private final String containerId;

        // How long to wait after shutdown (in milliseconds)
        private final int shutdownGracePeriod;

        // How long to wait after stop to kill container (in seconds)
        private final int killGracePeriod;

        // Whether to kill or stop gracefully
        private final StopMode stopMode;


        // Command to call before stopping container and whether to stop the build
        private String preStop;
        private boolean breakOnError = false;

        ContainerShutdownDescriptor(ImageConfiguration imageConfig, String containerId) {
            this.imageConfig = imageConfig;
            this.containerId = containerId;

            RunImageConfiguration runConfig = imageConfig.getRunConfiguration();
            WaitConfiguration waitConfig = runConfig != null ? runConfig.getWaitConfiguration() : null;
            this.shutdownGracePeriod = waitConfig != null && waitConfig.getShutdown() != null ? waitConfig.getShutdown() : 0;
            this.stopMode = runConfig != null ? runConfig.getStopMode()  : StopMode.graceful;
            this.killGracePeriod = waitConfig != null && waitConfig.getKill() != null ? waitConfig.getKill() : 0;
            if (waitConfig != null && waitConfig.getExec() != null) {
                this.preStop = waitConfig.getExec().getPreStop();
                this.breakOnError = waitConfig.getExec().isBreakOnError();
            }
        }

        public ImageConfiguration getImageConfiguration() {
            return imageConfig;
        }

        public String getImage() {
            return imageConfig.getName();
        }

        public String getContainerId() {
            return containerId;
        }

        public String getDescription() {
            return imageConfig.getDescription();
        }

        public int getShutdownGracePeriod() {
            return shutdownGracePeriod;
        }

        public int getKillGracePeriod() {
            return killGracePeriod;
        }

        public String getPreStop() {
            return preStop;
        }

        public boolean isBreakOnError() {
            return breakOnError;
        }

        public StopMode getStopMode() {
            return stopMode;
        }

        @Override
        public boolean equals(Object o) {
            if (this == o) return true;
            if (o == null || getClass() != o.getClass()) return false;

            ContainerShutdownDescriptor that = (ContainerShutdownDescriptor) o;

            return containerId.equals(that.containerId);

        }

        @Override
        public int hashCode() {
            return containerId.hashCode();
        }
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy