Skip to content

Commit

Permalink
Fix wouterd#38 Images that should be pushed but not kept are now deleted
Browse files Browse the repository at this point in the history
  • Loading branch information
Ardesco committed Feb 18, 2016
1 parent 36d133c commit 6309e1f
Show file tree
Hide file tree
Showing 5 changed files with 175 additions and 7 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ public abstract class AbstractDockerMojo extends AbstractMojo {
private static final String BUILT_IMAGES_KEY = "builtImages";
private static final String PUSHABLE_IMAGES_KEY = "pushableImages";
private static final String ERRORS_KEY = "errors";
protected static final String IMAGE_LIST_PROPERTY = "docker.containers.to.remove.after.push";

@Component
private RepositorySystem repositorySystem;
Expand Down Expand Up @@ -224,10 +225,10 @@ protected DockerProvider getDockerProvider() {
protected Credentials getCredentials() {
// priority to credentials from plugin configuration over the ones from settings
return Stream.of(getCredentialsFromParameters(), getCredentialsFromSettings())
.filter(Optional::isPresent)
.map(Optional::get)
.findFirst()
.orElse(null);
.filter(Optional::isPresent)
.map(Optional::get)
.findFirst()
.orElse(null);
}

private Optional<Credentials> getCredentialsFromParameters() {
Expand All @@ -240,12 +241,12 @@ private Optional<Credentials> getCredentialsFromParameters() {
}

private Optional<Credentials> getCredentialsFromSettings() {
if(settings == null) {
if (settings == null) {
getLog().debug("No settings.xml");
return empty();
}
Server server = settings.getServer(serverId);
if(server == null) {
if (server == null) {
getLog().debug("Cannot find server " + serverId + " in Maven settings");
return empty();
}
Expand Down
20 changes: 20 additions & 0 deletions src/main/java/net/wouterdanes/docker/maven/BuildImageMojo.java
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,9 @@
import org.apache.maven.plugins.annotations.LifecyclePhase;
import org.apache.maven.plugins.annotations.Mojo;
import org.apache.maven.plugins.annotations.Parameter;
import org.apache.maven.project.MavenProject;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
Expand All @@ -41,6 +43,9 @@ public class BuildImageMojo extends AbstractPreVerifyDockerMojo {
@Parameter(required = true)
private List<ImageBuildConfiguration> images;

@Parameter(defaultValue = "${project}", readonly = true)
private MavenProject project;

public void setImages(final List<ImageBuildConfiguration> images) {
this.images = images;
}
Expand All @@ -54,17 +59,28 @@ protected void doExecute() throws MojoExecutionException, MojoFailureException {

validateAllImages();

ArrayList<String> imagesToDeleteAfterPush = new ArrayList<>();

for (ImageBuildConfiguration image : images) {
try {
logImageConfig(image);
String imageId = getDockerProvider().buildImage(image);
getLog().info(String.format("Image '%s' has Id '%s'", image.getId(), imageId));
registerBuiltImage(imageId, image);
if (image.isPush() && !image.isKeep()) {
imagesToDeleteAfterPush.add(imageId);
}
} catch (DockerException e) {
String errorMessage = String.format("Cannot build image '%s'", image.getId());
handleDockerException(errorMessage, e);
}
}

if (imagesToDeleteAfterPush.size() > 0) {
String listOfImagesToDeleteAfterPush = String.join(",", imagesToDeleteAfterPush);
getLog().debug(String.format("Storing list of containers that need to be removed after a push: %s", listOfImagesToDeleteAfterPush));
project.getProperties().setProperty(IMAGE_LIST_PROPERTY, listOfImagesToDeleteAfterPush);
}
}

private void logImageConfig(final ImageBuildConfiguration image) {
Expand All @@ -87,6 +103,10 @@ private void validateAllImages() throws MojoExecutionException {
}
}

public void setProject(MavenProject project) {
this.project = project;
}

@Override
protected String getMojoGoalName() {
return "build-images";
Expand Down
22 changes: 22 additions & 0 deletions src/main/java/net/wouterdanes/docker/maven/PushImageMojo.java
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,12 @@
import org.apache.maven.plugins.annotations.InstantiationStrategy;
import org.apache.maven.plugins.annotations.LifecyclePhase;
import org.apache.maven.plugins.annotations.Mojo;
import org.apache.maven.plugins.annotations.Parameter;
import org.apache.maven.project.MavenProject;

import java.util.Arrays;
import java.util.Iterator;
import java.util.List;

/**
* This class is responsible for pushing docking images in the deploy phase of the maven build. The goal
Expand All @@ -36,6 +40,9 @@
instantiationStrategy = InstantiationStrategy.PER_LOOKUP)
public class PushImageMojo extends AbstractDockerMojo {

@Parameter(defaultValue = "${project}", readonly = true)
private MavenProject project;

@Override
public void doExecute() throws MojoExecutionException, MojoFailureException {
ensureThatAllPushableImagesHaveAName();
Expand All @@ -50,6 +57,18 @@ public void doExecute() throws MojoExecutionException, MojoFailureException {
handleDockerException(message, e);
}
}

String listOfImagesToDeleteAfterPush = project.getProperties().getProperty(IMAGE_LIST_PROPERTY);
if (listOfImagesToDeleteAfterPush != null) {
List<String> imageIDs = Arrays.asList(listOfImagesToDeleteAfterPush.split(","));
for (String imageID : imageIDs) {
try {
getDockerProvider().removeImage(imageID);
} catch (DockerException e) {
getLog().error("Failed to remove image", e);
}
}
}
}

private void ensureThatAllPushableImagesHaveAName() throws MojoFailureException {
Expand All @@ -65,4 +84,7 @@ private void ensureThatAllPushableImagesHaveAName() throws MojoFailureException
}
}

public void setProject(MavenProject project) {
this.project = project;
}
}
76 changes: 76 additions & 0 deletions src/test/java/net/wouterdanes/docker/maven/BuildImageMojoTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -24,25 +24,32 @@
import net.wouterdanes.docker.provider.model.PushableImage;
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.plugin.MojoFailureException;
import org.apache.maven.project.MavenProject;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.mockito.Mockito;

import java.util.*;

import static net.wouterdanes.docker.maven.AbstractDockerMojo.IMAGE_LIST_PROPERTY;
import static org.junit.Assert.*;
import static org.mockito.Matchers.any;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;

public class BuildImageMojoTest {

private static final String FAKE_PROVIDER_KEY = UUID.randomUUID().toString();
private static final String IMAGEID = UUID.randomUUID().toString();
private static final String STARTID = UUID.randomUUID().toString();
private static final String STARTIDTWO = UUID.randomUUID().toString();
private static final String NAMEANDTAG = UUID.randomUUID().toString();
private static final String NAMEANDTAGTWO = UUID.randomUUID().toString();
private static final String REGISTRY = UUID.randomUUID().toString();
private static final String REGISTRYANDNAMEANDTAG = REGISTRY + "/" + NAMEANDTAG;

private final MavenProject mavenProject = mock(MavenProject.class);
private BuildImageMojo mojo = new BuildImageMojo();

private ImageBuildConfiguration mockImage;
Expand All @@ -51,6 +58,9 @@ public class BuildImageMojoTest {
public void setUp() throws Exception {
mojo.setPluginContext(new HashMap());

Properties mavenProjectProperties = new Properties();
when(mavenProject.getProperties()).thenReturn(mavenProjectProperties);

FakeDockerProvider.instance = Mockito.mock(FakeDockerProvider.class);
Mockito.when(FakeDockerProvider.instance.buildImage(any(ImageBuildConfiguration.class))).thenReturn(IMAGEID);

Expand Down Expand Up @@ -134,8 +144,74 @@ public void testThatTheMojoThrowsAnExceptionWhenDuplicateImageIdsExist() throws
assertImageEnqueuedForPush(null);
}

@Test
public void imageListPropertyNotSetWhenImageIsPushAndIsKeep() throws Exception {
Mockito.when(mockImage.isPush()).thenReturn(true);
Mockito.when(mockImage.isKeep()).thenReturn(true);

executeMojo(FAKE_PROVIDER_KEY);

assertEquals(1, mojo.getImagesToPush().size());

PushableImage actual = mojo.getImagesToPush().get(0);

assertEquals(BuildImageMojoTest.IMAGEID, actual.getImageId());
assertEquals(null, mavenProject.getProperties().getProperty(IMAGE_LIST_PROPERTY));
}

@Test
public void imageListPropertyNotSetWhenImageIsNotPushAndIsNotKeep() throws Exception {
Mockito.when(mockImage.isPush()).thenReturn(false);
Mockito.when(mockImage.isKeep()).thenReturn(false);

executeMojo(FAKE_PROVIDER_KEY);

assertEquals(0, mojo.getImagesToPush().size());
assertEquals(null, mavenProject.getProperties().getProperty(IMAGE_LIST_PROPERTY));
}

@Test
public void imageListPropertySetWhenImageIsPushButNotIsKeep() throws Exception {
Mockito.when(mockImage.isPush()).thenReturn(true);
Mockito.when(mockImage.isKeep()).thenReturn(false);

executeMojo(FAKE_PROVIDER_KEY);

assertEquals(1, mojo.getImagesToPush().size());

assertEquals(mojo.getImagesToPush().get(0).getImageId(),
mavenProject.getProperties().getProperty(IMAGE_LIST_PROPERTY));
}

@Test
public void imageListPropertySetWhenMultipleImagesSetToIsPushButNotIsKeep() throws Exception {
Mockito.when(mockImage.isPush()).thenReturn(true);
Mockito.when(mockImage.isKeep()).thenReturn(false);

ImageBuildConfiguration mockImageTwo = Mockito.mock(ImageBuildConfiguration.class);
Mockito.when(mockImageTwo.getId()).thenReturn(STARTIDTWO);
Mockito.when(mockImageTwo.getNameAndTag()).thenReturn(NAMEANDTAGTWO);
Mockito.when(mockImageTwo.isPush()).thenReturn(true);
Mockito.when(mockImageTwo.isKeep()).thenReturn(false);

List<ImageBuildConfiguration> images = new ArrayList<>();
images.add(mockImage);
images.add(mockImageTwo);
mojo.setImages(images);

executeMojo(FAKE_PROVIDER_KEY);

assertEquals(2, mojo.getImagesToPush().size());

String expectedImageListPropertyValue = mojo.getImagesToPush().get(0).getImageId() + "," + mojo.getImagesToPush().get(1).getImageId();

assertEquals(expectedImageListPropertyValue,
mavenProject.getProperties().getProperty(IMAGE_LIST_PROPERTY));
}

private void executeMojo(String provider) throws MojoExecutionException, MojoFailureException {
mojo.setProviderName(provider);
mojo.setProject(mavenProject);
mojo.execute();
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,31 +21,46 @@
import net.wouterdanes.docker.provider.DockerProviderSupplier;
import net.wouterdanes.docker.provider.model.ImageBuildConfiguration;
import org.apache.maven.plugin.MojoFailureException;
import org.apache.maven.project.MavenProject;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.mockito.Matchers;
import org.mockito.Mockito;
import org.mockito.internal.verification.VerificationModeFactory;

import java.util.HashMap;
import java.util.Optional;
import java.util.Properties;
import java.util.UUID;

import static net.wouterdanes.docker.maven.AbstractDockerMojo.IMAGE_LIST_PROPERTY;
import static org.mockito.Mockito.*;

public class PushImageMojoTest {

private final String fakeProviderKey = UUID.randomUUID().toString();
private final MavenProject mavenProject = mock(MavenProject.class);
private PushImageMojo mojo;
private ImageBuildConfiguration mockImage;

private static final String NAME_AND_TAG = UUID.randomUUID().toString();

@Before
public void setUp() throws Exception {
Properties mavenProjectProperties = new Properties();
when(mavenProject.getProperties()).thenReturn(mavenProjectProperties);

mockImage = Mockito.mock(ImageBuildConfiguration.class);
Mockito.when(mockImage.getNameAndTag()).thenReturn(NAME_AND_TAG);
Mockito.when(mockImage.isPush()).thenReturn(true);

FakeDockerProvider.instance = mock(FakeDockerProvider.class);
DockerProviderSupplier.registerProvider(fakeProviderKey, FakeDockerProvider.class);

mojo = new PushImageMojo();
mojo.setPluginContext(new HashMap());

mojo.setProject(mavenProject);
mojo.setProviderName(fakeProviderKey);
}

Expand Down Expand Up @@ -74,6 +89,40 @@ public void testThatNoImagesArePushedWhenThereAreNoImagesMarkedToPush() throws E

}

@Test
public void willNotRemoveImagesIfImageListPropertyIsNotSet() throws Exception {

mojo.enqueueForPushing("some-image-id", mockImage);
mojo.enqueueForPushing("another-image-id", mockImage);
mojo.execute();

verify(FakeDockerProvider.instance, never()).removeImage(Matchers.<String>any());
}

@Test
public void willRemoveImagesIfImageListPropertyContainsASingleID() throws Exception {

mavenProject.getProperties().setProperty(IMAGE_LIST_PROPERTY, "some-image-id");

mojo.enqueueForPushing("some-image-id", mockImage);
mojo.enqueueForPushing("another-image-id", mockImage);
mojo.execute();

verify(FakeDockerProvider.instance, VerificationModeFactory.times(1)).removeImage(Matchers.<String>any());
}

@Test
public void willRemoveImagesIfImageListPropertyContainsMultipleIDs() throws Exception {

mavenProject.getProperties().setProperty(IMAGE_LIST_PROPERTY, "some-image-id,another-image-id");

mojo.enqueueForPushing("some-image-id", mockImage);
mojo.enqueueForPushing("another-image-id", mockImage);
mojo.execute();

verify(FakeDockerProvider.instance, VerificationModeFactory.times(2)).removeImage(Matchers.<String>any());
}

public static class FakeDockerProvider extends AbstractFakeDockerProvider {

private static FakeDockerProvider instance;
Expand Down

0 comments on commit 6309e1f

Please sign in to comment.