io.linguarobot.aws.cdk.maven.DockerImageAssetPublisher Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of aws-cdk-maven-plugin Show documentation
Show all versions of aws-cdk-maven-plugin Show documentation
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.
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