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

com.atlassian.bamboo.specs.model.task.docker.DockerRunContainerTaskProperties Maven / Gradle / Ivy

There is a newer version: 10.1.0
Show newest version
package com.atlassian.bamboo.specs.model.task.docker;


import com.atlassian.bamboo.specs.api.builders.docker.DockerConstants;
import com.atlassian.bamboo.specs.api.codegen.annotations.Builder;
import com.atlassian.bamboo.specs.api.codegen.annotations.CodeGenerator;
import com.atlassian.bamboo.specs.api.codegen.annotations.Setter;
import com.atlassian.bamboo.specs.api.exceptions.PropertiesValidationException;
import com.atlassian.bamboo.specs.api.model.plan.condition.ConditionProperties;
import com.atlassian.bamboo.specs.api.model.plan.requirement.RequirementProperties;
import com.atlassian.bamboo.specs.api.validators.common.ValidationContext;
import com.atlassian.bamboo.specs.builders.task.DockerRunContainerTask;
import com.atlassian.bamboo.specs.codegen.emitters.task.DockerRunContainerEmitter;
import org.apache.commons.lang3.StringUtils;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

import javax.annotation.concurrent.Immutable;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.stream.Collectors;

import static com.atlassian.bamboo.specs.api.validators.common.ImporterUtils.checkNotBlank;
import static com.atlassian.bamboo.specs.api.validators.common.ImporterUtils.checkNotNull;
import static com.atlassian.bamboo.specs.api.validators.common.ImporterUtils.checkPositive;
import static com.atlassian.bamboo.specs.api.validators.common.ImporterUtils.checkThat;

@Builder(DockerRunContainerTask.class)
@CodeGenerator(DockerRunContainerEmitter.class)
@Immutable
public final class DockerRunContainerTaskProperties extends AbstractDockerTaskProperties {

    public static final ValidationContext VALIDATION_CONTEXT = ValidationContext.of("Docker run container task:");

    public static final long DEFAULT_SERVICE_TIMEOUT = 120L;

    @NotNull
    private String imageName;
    @Setter("detachContainer")
    private boolean detachedContainer;
    @Nullable
    private String containerName;
    @NotNull
    private Map portMappings;
    private boolean waitToStart;
    private String serviceURLPattern;
    private long serviceTimeout;
    private boolean linkToDetachedContainers;
    @Nullable
    private String containerEnvironmentVariables;
    @Nullable
    private String containerCommand;
    @Nullable
    private String containerWorkingDirectory;
    @Nullable
    private String additionalArguments;
    @NotNull
    private Map volumeMappings;

    protected DockerRunContainerTaskProperties() {
        volumeMappings = new HashMap<>();
        volumeMappings.put(DockerConstants.DEFAULT_HOST_MAPPING, DockerConstants.DEFAULT_CONTAINER_MAPPING);

        workingSubdirectory = DockerConstants.DEFAULT_CONTAINER_MAPPING;
        serviceTimeout = DEFAULT_SERVICE_TIMEOUT;
    }

    public DockerRunContainerTaskProperties(@Nullable String description, boolean enabled,
                                            @NotNull String imageName,
                                            boolean detachedContainer,
                                            @Nullable String containerName,
                                            @NotNull Map portMappings,
                                            boolean waitToStart,
                                            @Nullable String serviceURLPattern,
                                            long serviceTimeout,
                                            boolean linkToDetachedContainers,
                                            @Nullable String containerEnvironmentVariables,
                                            @Nullable String containerCommand,
                                            @Nullable String containerWorkingDirectory,
                                            @Nullable String additionalArguments,
                                            @NotNull Map volumeMappings,
                                            @Nullable String environmentVariables,
                                            @Nullable String workingSubdirectory,
                                            @NotNull List requirements,
                                            @NotNull List conditions) throws PropertiesValidationException {
        super(description, enabled, environmentVariables, workingSubdirectory, requirements, conditions);
        this.imageName = imageName;
        this.detachedContainer = detachedContainer;
        this.containerName = containerName;
        this.portMappings = portMappings;
        this.waitToStart = waitToStart;
        this.serviceURLPattern = serviceURLPattern;
        this.serviceTimeout = serviceTimeout;
        this.linkToDetachedContainers = linkToDetachedContainers;
        this.containerEnvironmentVariables = containerEnvironmentVariables;
        this.containerCommand = containerCommand;
        this.containerWorkingDirectory = containerWorkingDirectory;
        this.additionalArguments = additionalArguments;
        this.volumeMappings = volumeMappings;

        validate();
    }


    @NotNull
    public String getImageName() {
        return imageName;
    }

    public boolean isDetachedContainer() {
        return detachedContainer;
    }

    @Nullable
    public String getContainerName() {
        return containerName;
    }

    public Map getPortMappings() {
        return portMappings == null ? Collections.emptyMap() : portMappings;
    }

    public boolean isWaitToStart() {
        return waitToStart;
    }

    public String getServiceURLPattern() {
        return serviceURLPattern;
    }

    public long getServiceTimeout() {
        return serviceTimeout;
    }

    public boolean isLinkToDetachedContainers() {
        return linkToDetachedContainers;
    }

    @Nullable
    public String getContainerEnvironmentVariables() {
        return containerEnvironmentVariables;
    }

    @Nullable
    public String getContainerCommand() {
        return containerCommand;
    }

    @Nullable
    public String getContainerWorkingDirectory() {
        return containerWorkingDirectory;
    }

    @Nullable
    public String getAdditionalArguments() {
        return additionalArguments;
    }

    @NotNull
    public Map getVolumeMappings() {
        return volumeMappings == null ? Collections.emptyMap() : volumeMappings;
    }

    @Override
    public void validate() {
        super.validate();

        checkNotBlank(VALIDATION_CONTEXT, "imageName", imageName);
        checkNotNull(VALIDATION_CONTEXT, "portMappings", portMappings);
        checkNotNull(VALIDATION_CONTEXT, "volumeMappings", volumeMappings);

        Set occupiedContainerPorts = new HashSet<>();

        for (Integer containerPort : portMappings.values()) {
            if (!occupiedContainerPorts.add(containerPort)) {
                throw new PropertiesValidationException(VALIDATION_CONTEXT, "Port " + containerPort + " is already defined.");
            }
        }

        Set occupiedContainerVolumes = new HashSet<>();

        for (String containerVolume : volumeMappings.values()) {
            if (!occupiedContainerVolumes.add(containerVolume)) {
                throw new PropertiesValidationException(VALIDATION_CONTEXT, "Volume " + containerVolume + " is already defined.");
            }
        }

        List invalidPorts = portMappings.entrySet()
                .stream()
                .filter(entry -> !isPortValid(entry.getKey()) || !isPortValid(entry.getValue()))
                .map(entry -> String.format("[%d,%d]", entry.getKey(), entry.getValue()))
                .collect(Collectors.toList());

        if (!invalidPorts.isEmpty()) {
            throw new PropertiesValidationException(VALIDATION_CONTEXT, "Specified port mappings are invalid: " + invalidPorts);
        }

        List invalidVolumeMappings = volumeMappings.entrySet().stream()
                .filter(entry -> StringUtils.isBlank(entry.getKey()) || StringUtils.isBlank(entry.getValue()))
                .map(entry -> String.format("[%s, %s]", entry.getKey(), entry.getValue()))
                .collect(Collectors.toList());

        if (!invalidVolumeMappings.isEmpty()) {
            throw new PropertiesValidationException(VALIDATION_CONTEXT, "Specified volume mappings are invalid: " + invalidVolumeMappings);
        }

        if (detachedContainer) {
            checkNotBlank(VALIDATION_CONTEXT, "containerName", containerName);
        }

        if (waitToStart) {
            checkNotBlank(VALIDATION_CONTEXT, "serviceURLPattern", serviceURLPattern);
            checkPositive(VALIDATION_CONTEXT, "serviceTimeout", serviceTimeout);
            checkThat(VALIDATION_CONTEXT, !portMappings.isEmpty(), "No port mappings defined");
        }
    }

    private boolean isPortValid(Integer port) {
        return port != null && port > 0 && port <= 65535;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) {
            return true;
        }
        if (o == null || getClass() != o.getClass()) {
            return false;
        }
        if (!super.equals(o)) {
            return false;
        }
        DockerRunContainerTaskProperties that = (DockerRunContainerTaskProperties) o;
        return detachedContainer == that.detachedContainer &&
                waitToStart == that.waitToStart &&
                serviceTimeout == that.serviceTimeout &&
                linkToDetachedContainers == that.linkToDetachedContainers &&
                Objects.equals(imageName, that.imageName) &&
                Objects.equals(containerName, that.containerName) &&
                Objects.equals(portMappings, that.portMappings) &&
                Objects.equals(serviceURLPattern, that.serviceURLPattern) &&
                Objects.equals(containerEnvironmentVariables, that.containerEnvironmentVariables) &&
                Objects.equals(containerCommand, that.containerCommand) &&
                Objects.equals(containerWorkingDirectory, that.containerWorkingDirectory) &&
                Objects.equals(additionalArguments, that.additionalArguments) &&
                Objects.equals(volumeMappings, that.volumeMappings);
    }

    @Override
    public int hashCode() {
        return Objects.hash(super.hashCode(), imageName, detachedContainer, containerName, portMappings, waitToStart,
                serviceURLPattern, serviceTimeout, linkToDetachedContainers, containerEnvironmentVariables,
                containerCommand, containerWorkingDirectory, additionalArguments, volumeMappings);
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy