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

io.linguarobot.aws.cdk.maven.DockerImageAssetPublisher Maven / Gradle / Ivy

Go to download

The AWS CDK Maven plugin produces and deploys CloudFormation templates based on the cloud infrastructure defined by means of CDK. The goal of the project is to improve the experience of Java developers while working with CDK by eliminating the need for installing Node.js and interacting with the CDK application by means of CDK Toolkit.

There is a newer version: 0.0.8
Show newest version
package io.linguarobot.aws.cdk.maven;

import com.google.common.collect.ImmutableList;
import io.linguarobot.aws.cdk.maven.process.ProcessExecutionException;
import io.linguarobot.aws.cdk.maven.process.ProcessRunner;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import software.amazon.awssdk.services.ecr.EcrClient;
import software.amazon.awssdk.services.ecr.model.AuthorizationData;
import software.amazon.awssdk.services.ecr.model.CreateRepositoryRequest;
import software.amazon.awssdk.services.ecr.model.CreateRepositoryResponse;
import software.amazon.awssdk.services.ecr.model.DescribeImagesRequest;
import software.amazon.awssdk.services.ecr.model.DescribeImagesResponse;
import software.amazon.awssdk.services.ecr.model.DescribeRepositoriesRequest;
import software.amazon.awssdk.services.ecr.model.DescribeRepositoriesResponse;
import software.amazon.awssdk.services.ecr.model.ImageDetail;
import software.amazon.awssdk.services.ecr.model.ImageIdentifier;
import software.amazon.awssdk.services.ecr.model.ImageNotFoundException;
import software.amazon.awssdk.services.ecr.model.Repository;
import software.amazon.awssdk.services.ecr.model.RepositoryNotFoundException;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Base64;
import java.util.List;
import java.util.Optional;

public class DockerImageAssetPublisher {

    private static final Logger logger = LoggerFactory.getLogger(DockerImageAssetPublisher.class);

    private final ResolvedEnvironment environment;
    private final ProcessRunner processRunner;

    private EcrClient ecrClient;

    public DockerImageAssetPublisher(ResolvedEnvironment environment,ProcessRunner processRunner) {
        this.environment = environment;
        this.processRunner = processRunner;
    }

    /**
     * Builds the given using the specified build parameters and published the built image to ECR.
     *
     * @param repositoryName the name of the repository
     * @param tag image tag
     * @param imageBuild build definition
     */
    public void publish(String repositoryName, String tag, ImageBuild imageBuild) {
        ImageDetail image = findImage(repositoryName, tag).orElse(null);
        if (image == null) {
            ensureDockerInstalled();

            AuthorizationData authorizationData = getAuthorizationData()
                    .orElseThrow(() -> new CdkPluginException("Unable to retrieve authorization token from ECR"));
            try {
                processRunner.run(toDockerLoginCommand(authorizationData));
            } catch (ProcessExecutionException e) {
                throw new CdkPluginException("Unable to add ECR authorization data");
            }

            logger.info("Building docker image before publishing it to the ECR, dockerFile={}", imageBuild.getDockerfile());
            try {
                processRunner.run(toBuildCommand(imageBuild));
            } catch (ProcessExecutionException e) {
                throw new CdkPluginException("Failed to build the docker image from " + imageBuild.getDockerfile() +
                        ". Please make sure that the Docker daemon is running");
            }

            Repository repository = findRepository(repositoryName)
                    .orElseGet(() -> createRepository(repositoryName));
            String imageUri = String.join(":", repository.repositoryUri(), tag);
            processRunner.run(ImmutableList.of("docker", "tag", imageBuild.getImageTag(), imageUri));

            logger.info("Publishing docker image, imageUri={}", imageUri);
            try {
                processRunner.run(ImmutableList.of("docker", "push", imageUri));
            } catch (ProcessExecutionException e) {
                throw new CdkPluginException("Unable to push the image " + imageUri + " to the ECR repository");
            }
        }
    }

    private void ensureDockerInstalled() {
        try {
            processRunner.run(Arrays.asList("docker", "--version"));
        } catch (ProcessExecutionException e) {
            throw new CdkPluginException("Docker is required in order to build container assets");
        }
    }

    private void login() {
        AuthorizationData authorizationData = getAuthorizationData()
                .orElseThrow(() -> new CdkPluginException("Unable to retrieve authorization token from ECR"));

        processRunner.run(toDockerLoginCommand(authorizationData));
    }

    private List toBuildCommand(ImageBuild build) {
        List buildCommand = new ArrayList<>();
        buildCommand.add("docker");
        buildCommand.add("build");
        buildCommand.add("--tag");
        buildCommand.add(build.getImageTag());

        build.getArguments().forEach((name, value) -> {
            buildCommand.add("--build-arg");
            buildCommand.add(String.join("=", name, value));
        });
        if (build.getTarget() != null) {
            buildCommand.add("--target");
            buildCommand.add(build.getTarget());
        }
        if (build.getDockerfile() != null) {
            buildCommand.add("--file");
            buildCommand.add(build.getContextDirectory().relativize(build.getDockerfile()).toString());
        }
        buildCommand.add(build.getContextDirectory().toString());

        return buildCommand;
    }

    private EcrClient getEcrClient() {
        if (this.ecrClient == null) {
            this.ecrClient = EcrClient.builder()
                    .region(environment.getRegion())
                    .credentialsProvider(environment.getCredentialsProvider())
                    .build();
        }

        return ecrClient;
    }

    private List toDockerLoginCommand(AuthorizationData authorizationData) {
        String[] userPassword = new String(Base64.getDecoder().decode(authorizationData.authorizationToken())).split(":");
        return ImmutableList.of("docker", "login",
                "--username", userPassword[0],
                "--password", userPassword[1],
                authorizationData.proxyEndpoint()
        );
    }

    private Optional findImage(String repositoryName, String imageTag) {
        DescribeImagesRequest describeRequest = DescribeImagesRequest.builder()
                .repositoryName(repositoryName)
                .imageIds(ImageIdentifier.builder()
                        .imageTag(imageTag)
                        .build())
                .build();
        try {
            DescribeImagesResponse response = getEcrClient().describeImages(describeRequest);
            return response.imageDetails().stream().findFirst();
        } catch (ImageNotFoundException|RepositoryNotFoundException e) {
            return Optional.empty();
        }
    }

    private Optional findRepository(String name) {
        DescribeRepositoriesRequest describeRequest = DescribeRepositoriesRequest.builder()
                .repositoryNames(name)
                .build();
        try {
            DescribeRepositoriesResponse response = getEcrClient().describeRepositories(describeRequest);
            return response.repositories().stream()
                    .findFirst();
        } catch (RepositoryNotFoundException e) {
            return Optional.empty();
        }
    }

    private Repository createRepository(String name) {
        CreateRepositoryRequest createRequest = CreateRepositoryRequest.builder()
                .repositoryName(name)
                .build();
        CreateRepositoryResponse response = getEcrClient().createRepository(createRequest);
        return response.repository();
    }

    private Optional getAuthorizationData() {
        return getEcrClient().getAuthorizationToken().authorizationData().stream().findFirst();
    }

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy