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

io.fabric8.maven.docker.util.ContainerNamingUtil Maven / Gradle / Ivy

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

import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import java.util.function.Function;
import java.util.stream.Collectors;

import com.google.common.collect.ImmutableSet;
import io.fabric8.maven.docker.config.ImageConfiguration;
import io.fabric8.maven.docker.config.RunImageConfiguration;
import io.fabric8.maven.docker.model.Container;

/**
 * @author marcus
 * @since 1.0.0
 */
public class ContainerNamingUtil {

    private static final String INDEX_PLACEHOLDER = "%i";

    public static final String DEFAULT_CONTAINER_NAME_PATTERN = "%n-%i";

    // class with only static methods
    private ContainerNamingUtil() { }

    public static String formatContainerName(final ImageConfiguration image,
                                             final String defaultContainerNamePattern,
                                             final Date buildTimestamp,
                                             final Collection existingContainers) {

        String containerNamePattern = extractContainerNamePattern(image, defaultContainerNamePattern);
        Set existingContainersNames = extractContainerNames(existingContainers);

        final String partiallyApplied =
            replacePlaceholders(
                containerNamePattern,
                image.getName(),
                image.getAlias(),
                buildTimestamp);


        if (partiallyApplied.contains(INDEX_PLACEHOLDER)) {
            for (long i = 1; i < Long.MAX_VALUE; i++) {
                final String withIndexApplied = partiallyApplied.replaceAll(INDEX_PLACEHOLDER, String.valueOf(i));
                if (!existingContainersNames.contains(withIndexApplied)) {
                    return withIndexApplied;
                }
            }
            throw new IllegalStateException("Could not find any free container name for pattern " + partiallyApplied);
        } else {
            return partiallyApplied;
        }
    }

    /**
     * Keep only the entry with the higest index if an indexed naming scheme for container has been chosen.
     * @param image the image from which to the the container pattern
     * @param buildTimestamp the timestamp for the build
     * @param containers the list of existing containers
     * @return a list with potentially lower indexed entries removed
     */
    public static Collection getContainersToStop(final ImageConfiguration image,
                                                            final String defaultContainerNamePattern,
                                                            final Date buildTimestamp,
                                                            final Collection containers) {

        String containerNamePattern = extractContainerNamePattern(image, defaultContainerNamePattern);

        // Only special treatment for indexed container names
        if (!containerNamePattern.contains(INDEX_PLACEHOLDER)) {
            return containers;
        }

        final String partiallyApplied =
            replacePlaceholders(
                containerNamePattern,
                image.getName(),
                image.getAlias(),
                buildTimestamp);

        return keepOnlyLastIndexedContainer(containers, partiallyApplied);

    }

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

    private static String replacePlaceholders(String containerNamePattern, String imageName, String nameAlias, Date buildTimestamp) {

        Map lookups = new HashMap<>();

        lookups.put("a", () -> nameAlias);
        lookups.put("n", () -> cleanImageName(imageName));
        lookups.put("t", () -> String.valueOf(buildTimestamp.getTime()));
        lookups.put("i", () -> INDEX_PLACEHOLDER);

        return new FormatParameterReplacer(lookups).replace(containerNamePattern);
    }


    // Filter out any older indexed containernames, keeping only the last one (i.e. with the highest index)
    private static Collection keepOnlyLastIndexedContainer(Collection existingContainers, final String partiallyApplied) {

        Collection result = new ArrayList<>(existingContainers);

        // No index place holder, so nothing to filters
        if (!partiallyApplied.contains(INDEX_PLACEHOLDER)) {
            return result;
        }

        Map containerMap = existingContainers.stream().collect(Collectors.toMap(Container::getName, Function.identity()));

        Container last = null;
        for (long i = 1; i < Long.MAX_VALUE; i++) {
            final String withIndexApplied = partiallyApplied.replaceAll(INDEX_PLACEHOLDER, String.valueOf(i));
            Container mapped = containerMap.get(withIndexApplied);
            if (mapped != null) {
                result.remove(mapped);
                last = mapped;
            } else {
                // Readd last one removed (if any)
                if (last != null) {
                    result.add(last);
                }
                return result;
            }
        }
        throw new IllegalStateException("Internal error: Cannot find a free container index slot in " + existingContainers);
    }

    private static Set extractContainerNames(final Collection existingContainers) {
        final ImmutableSet.Builder containerNamesBuilder = ImmutableSet.builder();
        for (final Container container : existingContainers) {
            containerNamesBuilder.add(container.getName());
        }
        return containerNamesBuilder.build();
    }

    private static String extractContainerNamePattern(ImageConfiguration image, String defaultContainerNamePattern) {
        RunImageConfiguration runConfig = image.getRunConfiguration();
        if (runConfig != null) {
            if (runConfig.getContainerNamePattern() != null) {
                return runConfig.getContainerNamePattern();
            }
            if (runConfig.getNamingStrategy() == RunImageConfiguration.NamingStrategy.alias) {
                return "%a";
            }
        }
        return defaultContainerNamePattern != null ? defaultContainerNamePattern : DEFAULT_CONTAINER_NAME_PATTERN;
    }

    private static String cleanImageName(final String imageName) {
        return new ImageName(imageName).getSimpleName().replaceAll("[^a-zA-Z0-9_.-]+", "_");
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy