Skip to content

Commit

Permalink
Fix wouterd#31 Write all exposed ports to a docker mappings file (def…
Browse files Browse the repository at this point in the history
…aults to ${project.build.directory}/docker-plugin/docker-mappings.properties)
  • Loading branch information
Ardesco committed Feb 18, 2016
1 parent 36d133c commit f1531af
Show file tree
Hide file tree
Showing 3 changed files with 89 additions and 16 deletions.
8 changes: 8 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,7 @@ pom.xml here: [pom.xml](https://github.com/wouterd/docker-maven-plugin/blob/mast
at the end of the build even if the stop-containers goal is not executed
(useful for preventing Ctrl+C causing dangling containers) -->
<forceCleanup>false</forceCleanup>
<dockerMappingsFile/>
<containers>
<container>
<id>mongo</id>
Expand Down Expand Up @@ -163,6 +164,13 @@ By default, all exposed ports are published on the host. The following two prope
- docker.containers.[id].ports.[portname].host (f.ex 'docker.containers.id.app.ports.80/tcp.host')
- docker.containers.[id].ports.[portname].port (f.ex 'docker.containers.id.app.ports.80/tcp.port')

All properties are also added to the file `${project.build.directory}/docker-plugin/docker-mappings.properties` so that you can easily load this properties file into your integration tests.
You can change the name or location of this file by modifying `<dockerMappingsFile>` in the configuration block of the start-containers execution block.

<dockerMappingsFile>${project.build.directory}/docker-plugin/docker-mappings.properties</dockerMappingsFile>

The location specified above is also exposed as a maven variable called `${docker.mappings.file}`

You can pass those project properties over to your integration test and use them to connect to your application.

The plugin will connect to a docker instance over HTTP, linux socket support will be added after 1.0. It will look up
Expand Down
58 changes: 49 additions & 9 deletions src/main/java/net/wouterdanes/docker/maven/StartContainerMojo.java
Original file line number Diff line number Diff line change
Expand Up @@ -34,9 +34,15 @@
import org.apache.maven.project.MavenProject;

import javax.inject.Inject;
import java.io.BufferedWriter;
import java.io.File;
import java.io.IOException;
import java.nio.file.*;
import java.util.*;
import java.util.regex.Pattern;

import static java.nio.file.StandardOpenOption.APPEND;

/**
* This class is responsible for starting docking containers in the pre-integration phase of the maven build. The goal
* is called "start-containers"
Expand All @@ -62,11 +68,15 @@ public StartContainerMojo(List<ContainerStartConfiguration> containers) {
@Parameter(defaultValue = "${mojoExecution}", readonly = true)
private MojoExecution mojoExecution;

@Parameter(defaultValue = "${project.build.directory}/docker-plugin/docker-mappings.properties")
private File dockerMappingsFile;

@Override
public void doExecute() throws MojoExecutionException, MojoFailureException {
if (hasDuplicateIds() || hasInvalidLinks()) {
return;
}
generateMappingsFile();
DockerProvider provider = getDockerProvider();
for (ContainerStartConfiguration configuration : containers) {
for (ContainerLink link : configuration.getLinks()) {
Expand All @@ -84,6 +94,7 @@ public void doExecute() throws MojoExecutionException, MojoFailureException {
String containerId = container.getId();
List<ExposedPort> exposedPorts = provider.getExposedPorts(containerId);
exposePortsToProject(configuration, exposedPorts);
writeListOfPortsToFile(configuration, exposedPorts);
getLog().info(String.format("Started container with id '%s'", containerId));
registerStartedContainer(configuration.getId(), container);
} catch (DockerException e) {
Expand All @@ -98,15 +109,14 @@ public void doExecute() throws MojoExecutionException, MojoFailureException {
}
}

/** Avoid dangling containers if the build is interrupted (e.g. via Ctrl+C) before the StopContainer mojo runs. */
private void addShutdownHookToCleanUpContainers()
{
/**
* Avoid dangling containers if the build is interrupted (e.g. via Ctrl+C) before the StopContainer mojo runs.
*/
private void addShutdownHookToCleanUpContainers() {
getLog().info("Started containers will be forcibly cleaned up when the build finishes");
Runtime.getRuntime().addShutdownHook(new Thread(new Runnable()
{
Runtime.getRuntime().addShutdownHook(new Thread(new Runnable() {
@Override
public void run()
{
public void run() {
cleanUpStartedContainers();
}
}));
Expand Down Expand Up @@ -193,13 +203,39 @@ private boolean hasDuplicateIds() {

private void exposePortsToProject(ContainerStartConfiguration configuration, List<ExposedPort> exposedPorts) {
exposedPorts.parallelStream().forEach(port -> {
String prefix = String.format("docker.containers.%s.ports.%s.",
configuration.getId(), port.getContainerPort());
String prefix = String.format("docker.containers.%s.ports.%s.", configuration.getId(), port.getContainerPort());
addPropertyToProject(prefix + "host", port.getHost());
addPropertyToProject(prefix + "port", String.valueOf(port.getExternalPort()));
});
}

private void generateMappingsFile() throws MojoExecutionException {
try {
if (dockerMappingsFile.getParentFile() != null) {
Files.createDirectories(dockerMappingsFile.getParentFile().toPath());
}
Files.createFile(dockerMappingsFile.toPath());
addPropertyToProject("docker.mappings.file", dockerMappingsFile.getAbsolutePath());
} catch (IOException e) {
throw new MojoExecutionException("Error generating docker mapping file: ", e);
}
}

private void writeListOfPortsToFile(ContainerStartConfiguration configuration, List<ExposedPort> exposedPorts) throws MojoExecutionException {
try (BufferedWriter writer = Files.newBufferedWriter(dockerMappingsFile.toPath(), APPEND)) {
getLog().info(String.format("Writing properties for container '%s' to '%s'", configuration.getId(), dockerMappingsFile.getName()));
for (ExposedPort port : exposedPorts) {
String prefix = String.format("docker.containers.%s.ports.%s.", configuration.getId(), port.getContainerPort());
writer.write(prefix + "host=" + port.getHost());
writer.newLine();
writer.write(prefix + "port=" + String.valueOf(port.getExternalPort()));
writer.newLine();
}
} catch (IOException e) {
throw new MojoExecutionException("Error writing to docker mapping file: ", e);
}
}

private void replaceImageWithBuiltImageIdIfInternalId(ContainerStartConfiguration configuration) {
Optional<BuiltImageInfo> builtImage = getBuiltImageForStartId(configuration.getImage());
if (builtImage.isPresent()) {
Expand Down Expand Up @@ -227,6 +263,10 @@ public void setMojoExecution(final MojoExecution mojoExecution) {
this.mojoExecution = mojoExecution;
}

public void setDockerMappingsFile(File dockerMappingsFile) {
this.dockerMappingsFile = dockerMappingsFile;
}

private void addPropertyToProject(String key, String value) {
getLog().info(String.format("Setting property '%s' to '%s'", key, value));
project.getProperties().setProperty(key, value);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,14 +28,20 @@
import org.apache.maven.plugin.MojoExecution;
import org.apache.maven.project.MavenProject;
import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.mockito.ArgumentCaptor;
import org.mockito.Matchers;
import org.mockito.invocation.InvocationOnMock;
import org.mockito.stubbing.Answer;

import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.*;
import java.util.stream.Stream;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
Expand All @@ -45,6 +51,7 @@
public class StartContainerMojoTest {

private static final String FAKE_PROVIDER_KEY = UUID.randomUUID().toString();
private static final String DOCKER_MAPPINGS_FILE = System.getProperty("java.io.tmpdir") + File.separator + "docker-maven-plugin" + File.separator + "docker-mappings.properties";

private final MavenProject mavenProject = mock(MavenProject.class);
private final MojoExecution mojoExecution = new MojoExecution(null, "start-containers", "some-id");
Expand All @@ -69,6 +76,7 @@ public void setUp() throws Exception {
@After
public void tearDown() throws Exception {
DockerProviderSupplier.removeProvider(FAKE_PROVIDER_KEY);
Files.deleteIfExists(Paths.get(DOCKER_MAPPINGS_FILE));
}

@Test
Expand Down Expand Up @@ -285,8 +293,8 @@ public void testThatContainerWaitsForLinkedContainerToStart() throws Exception {
final ContainerStartConfiguration parent = new ContainerStartConfiguration()
.withId("parent")
.withLink(new ContainerLink()
.toContainer("linked")
.withAlias("database")
.toContainer("linked")
.withAlias("database")
);

when(FakeDockerProvider.instance.getLogs("linked")).thenReturn("", "", "there");
Expand All @@ -311,15 +319,15 @@ public Object answer(final InvocationOnMock invocation) throws Throwable {

@Test
public void testThatMojoStartsAContainerOnTheProviderWithEnvironmentVariables() throws Exception {
Map<String, String> env = new HashMap<>();
env.put("TEST_KEY", "test value");
Map<String, String> env = new HashMap<>();
env.put("TEST_KEY", "test value");

ContainerStartConfiguration startConfiguration = new ContainerStartConfiguration()
.withEnv(env);
.withEnv(env);
StartContainerMojo mojo = createMojo(startConfiguration);

mojo.execute();

ArgumentCaptor<ContainerStartConfiguration> captor = ArgumentCaptor.forClass(ContainerStartConfiguration.class);
verify(FakeDockerProvider.instance).startContainer(captor.capture());

Expand Down Expand Up @@ -361,6 +369,22 @@ public void testThatConfiguredMacAddressGetsPassedToDocker() throws Exception {
assertEquals("12:34:56:78:9a:bc", passedValue.getMacAddress());
}

@Test
public void testThatDockerMappingsFileIsCreated() throws Exception {
ContainerStartConfiguration startConfiguration = new ContainerStartConfiguration();
StartContainerMojo mojo = createMojo(startConfiguration);

File dockerMappingsFile = new File(DOCKER_MAPPINGS_FILE);

assertEquals(dockerMappingsFile.exists(), false);

mojo.execute();

verify(FakeDockerProvider.instance).startContainer(startConfiguration);

assertEquals(dockerMappingsFile.exists(), true);
}

private StartContainerMojo createMojo(final ContainerStartConfiguration startConfiguration) {
return createMojo(startConfiguration, FAKE_PROVIDER_KEY);
}
Expand All @@ -375,6 +399,7 @@ private StartContainerMojo createMojo(List<ContainerStartConfiguration> startCon
mojo.setProviderName(provider);
mojo.setPluginContext(new HashMap());
mojo.setMojoExecution(mojoExecution);
mojo.setDockerMappingsFile(new File(DOCKER_MAPPINGS_FILE));

return mojo;
}
Expand Down

0 comments on commit f1531af

Please sign in to comment.