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

nl.lexemmens.podman.helper.ImageNameHelper Maven / Gradle / Ivy

package nl.lexemmens.podman.helper;

import nl.lexemmens.podman.config.image.StageConfiguration;
import nl.lexemmens.podman.config.image.single.SingleImageConfiguration;
import org.apache.maven.project.MavenProject;

import java.nio.file.Path;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * Helper class to format image names.
 * 

* Supported formatter options: *

    *
  • %a: Results in the artifactId (sanitized)
  • *
  • %d: Results in the directory that contains the Containerfile
  • *
  • %g: Results in the last part of the groupId (after the last .)
  • *
  • %n: Results in a number (starting at 0)
  • *
  • %l: Results in 'latest' in case the current version is a SNAPSHOT. Otherwise version of the project
  • *
  • %t: Results in 'snapshot-[timestamp]'
  • *
  • %v: Results in the version of the project
  • *
*/ public class ImageNameHelper { private final MavenProject mavenProject; private final ParameterReplacer parameterReplacer; /** * Constructs a new instance of this {@link ImageNameHelper} * * @param mavenProject The MavenProject to use */ public ImageNameHelper(MavenProject mavenProject) { this.mavenProject = mavenProject; this.parameterReplacer = new ParameterReplacer(initReplacements()); } /** * Adapt some replacements based on the new {@link SingleImageConfiguration}. *

* Some replacements may be based on some properties from the {@link SingleImageConfiguration}. This method * ensures that they are all adapted and that the call to {@link #formatImageName(SingleImageConfiguration)} returns * the correct value. * * @param imageConfiguration The {@link SingleImageConfiguration} to use */ public void adaptReplacemeents(SingleImageConfiguration imageConfiguration) { parameterReplacer.adaptReplacements(imageConfiguration); } /** * Formats the imageName according to the specifications from this class. Both image names as specified * in the 'name' tag and the 'imageName' tag (part of the stage section) are being proessed. * * @param imageConfiguration The imageConfiguration containing the image names to format. */ public void formatImageName(SingleImageConfiguration imageConfiguration) { String imageName = parameterReplacer.replace(imageConfiguration.getImageName()); imageConfiguration.setImageName(imageName); if (imageConfiguration.useCustomImageNameForMultiStageContainerfile() && imageConfiguration.getStages() != null && imageConfiguration.getStages().length > 0) { for (StageConfiguration stage : imageConfiguration.getStages()) { if (stage.getImageName() == null) { stage.setImageName(imageName); continue; } String stageImageName = parameterReplacer.replace(stage.getImageName()); stage.setImageName(stageImageName); } } } private Map initReplacements() { final Map replacements = new HashMap<>(); replacements.put("a", new ArtifactIdReplacement()); replacements.put("d", new ContainerFileDirectoryReplacement()); replacements.put("g", new GroupIdReplacement()); replacements.put("n", new ImageNumberReplacement()); replacements.put("l", new SnapshotLatestReplacement()); replacements.put("t", new SnapshotTimestampReplacement()); replacements.put("v", new ProjectVersionReplacement()); return replacements; } /** * Replacement that replaces a preconfigured character with the artifactId of the Maven Project. */ private class ArtifactIdReplacement implements ParameterReplacer.Replacement { @Override public void adaptReplacement(SingleImageConfiguration notUsed) { // Ignore } @Override public String get() { return alignWithNamingConvention(mavenProject.getArtifactId()); } } /** * Replacement that replaces a preconfigured character with the version of the Maven Project. */ private class ProjectVersionReplacement implements ParameterReplacer.Replacement { @Override public void adaptReplacement(SingleImageConfiguration notUsed) { // Ignore } @Override public String get() { return alignWithNamingConvention(mavenProject.getVersion()); } } /** * Replacement that replaces a preconfigured character with 'latest' when the project's * version ends with '-SNAPSHOT'. Otherwise it will return the version of the project. */ private class SnapshotLatestReplacement implements ParameterReplacer.Replacement { @Override public void adaptReplacement(SingleImageConfiguration notUsed) { // Ignore } @Override public String get() { String version = mavenProject.getVersion(); if (version.endsWith("-SNAPSHOT")) { version = "latest"; } return alignWithNamingConvention(version); } } /** * Replacement that replaces a preconfigured character with last part of the * Maven groupId. */ private class GroupIdReplacement implements ParameterReplacer.Replacement { @Override public void adaptReplacement(SingleImageConfiguration notUsed) { // Ignore } @Override public String get() { String groupId = mavenProject.getGroupId(); int idx = groupId.lastIndexOf('.'); if (idx != -1) { groupId = groupId.substring(idx + 1); } return alignWithNamingConvention(groupId); } } /** * Replacement that replaces a preconfigured character with 'snapshot-[timestamp]'. The * timestamp will be in format 'yyMMdd-HHmmss-SSSS'. */ private static class SnapshotTimestampReplacement implements ParameterReplacer.Replacement { private final SimpleDateFormat dateFormat = new SimpleDateFormat("yyMMdd-HHmmss-SSSS"); @Override public void adaptReplacement(SingleImageConfiguration notUsed) { // Ignore } @Override public String get() { Calendar now = Calendar.getInstance(); dateFormat.setTimeZone(now.getTimeZone()); return alignWithNamingConvention("snapshot-" + dateFormat.format(now.getTime())); } } /** * Replacement that replaces a preconfigured character with the name of the directory * the Containerfile is in. */ private static class ContainerFileDirectoryReplacement implements ParameterReplacer.Replacement { Path containerFileDirectory; @Override public void adaptReplacement(SingleImageConfiguration image) { this.containerFileDirectory = image.getBuild().getSourceContainerFileDir(); } @Override public String get() { // /someDirectory/subFolder/Containerfile => subFolder return alignWithNamingConvention(containerFileDirectory.getParent().getFileName().toString()); } } /** * Replacement that replaces a preconfigured character with a zero based integer. */ private static class ImageNumberReplacement implements ParameterReplacer.Replacement { AtomicInteger imageNumber = new AtomicInteger(0); @Override public void adaptReplacement(SingleImageConfiguration notUsed) { // Ignore } @Override public String get() { return alignWithNamingConvention(String.format("%s", imageNumber.getAndIncrement())); } } /** * As per Docker's naming conventions, image names must meet the following criteria: *

    *
  • Name components may contain lowercase letters, digits and separators.
  • *
  • A separator is defined as: *
      *
    • a period
    • *
    • one or two underscores
    • *
    • one or more dashes
    • *
    *
  • *
  • A name component may not start or end with a separator.
  • *
* * @param imageName The image name to * @return The image name, meeting the image naming conventions * @see Docker docs */ private static String alignWithNamingConvention(String imageName) { StringBuilder ret = new StringBuilder(); int underscores = 0; boolean lastWasADot = false; for (char character : imageName.toCharArray()) { if (character == '_') { underscores++; // Max 2 underscores after eachother if (underscores <= 2) { ret.append(character); } continue; } if (character == '.') { // Only one dot is allowed if (!lastWasADot) { ret.append(character); } lastWasADot = true; continue; } underscores = 0; lastWasADot = false; if (Character.isLetter(character) || Character.isDigit(character) || character == '-') { ret.append(character); } } // All characters must be lowercase return ret.toString().toLowerCase(); } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy