Skip to content

Commit f1531af

Browse files
committed
Fix #31 Write all exposed ports to a docker mappings file (defaults to ${project.build.directory}/docker-plugin/docker-mappings.properties)
1 parent 36d133c commit f1531af

File tree

3 files changed

+89
-16
lines changed

3 files changed

+89
-16
lines changed

README.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,7 @@ pom.xml here: [pom.xml](https://github.com/wouterd/docker-maven-plugin/blob/mast
8686
at the end of the build even if the stop-containers goal is not executed
8787
(useful for preventing Ctrl+C causing dangling containers) -->
8888
<forceCleanup>false</forceCleanup>
89+
<dockerMappingsFile/>
8990
<containers>
9091
<container>
9192
<id>mongo</id>
@@ -163,6 +164,13 @@ By default, all exposed ports are published on the host. The following two prope
163164
- docker.containers.[id].ports.[portname].host (f.ex 'docker.containers.id.app.ports.80/tcp.host')
164165
- docker.containers.[id].ports.[portname].port (f.ex 'docker.containers.id.app.ports.80/tcp.port')
165166

167+
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.
168+
You can change the name or location of this file by modifying `<dockerMappingsFile>` in the configuration block of the start-containers execution block.
169+
170+
<dockerMappingsFile>${project.build.directory}/docker-plugin/docker-mappings.properties</dockerMappingsFile>
171+
172+
The location specified above is also exposed as a maven variable called `${docker.mappings.file}`
173+
166174
You can pass those project properties over to your integration test and use them to connect to your application.
167175

168176
The plugin will connect to a docker instance over HTTP, linux socket support will be added after 1.0. It will look up

src/main/java/net/wouterdanes/docker/maven/StartContainerMojo.java

Lines changed: 49 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -34,9 +34,15 @@
3434
import org.apache.maven.project.MavenProject;
3535

3636
import javax.inject.Inject;
37+
import java.io.BufferedWriter;
38+
import java.io.File;
39+
import java.io.IOException;
40+
import java.nio.file.*;
3741
import java.util.*;
3842
import java.util.regex.Pattern;
3943

44+
import static java.nio.file.StandardOpenOption.APPEND;
45+
4046
/**
4147
* This class is responsible for starting docking containers in the pre-integration phase of the maven build. The goal
4248
* is called "start-containers"
@@ -62,11 +68,15 @@ public StartContainerMojo(List<ContainerStartConfiguration> containers) {
6268
@Parameter(defaultValue = "${mojoExecution}", readonly = true)
6369
private MojoExecution mojoExecution;
6470

71+
@Parameter(defaultValue = "${project.build.directory}/docker-plugin/docker-mappings.properties")
72+
private File dockerMappingsFile;
73+
6574
@Override
6675
public void doExecute() throws MojoExecutionException, MojoFailureException {
6776
if (hasDuplicateIds() || hasInvalidLinks()) {
6877
return;
6978
}
79+
generateMappingsFile();
7080
DockerProvider provider = getDockerProvider();
7181
for (ContainerStartConfiguration configuration : containers) {
7282
for (ContainerLink link : configuration.getLinks()) {
@@ -84,6 +94,7 @@ public void doExecute() throws MojoExecutionException, MojoFailureException {
8494
String containerId = container.getId();
8595
List<ExposedPort> exposedPorts = provider.getExposedPorts(containerId);
8696
exposePortsToProject(configuration, exposedPorts);
97+
writeListOfPortsToFile(configuration, exposedPorts);
8798
getLog().info(String.format("Started container with id '%s'", containerId));
8899
registerStartedContainer(configuration.getId(), container);
89100
} catch (DockerException e) {
@@ -98,15 +109,14 @@ public void doExecute() throws MojoExecutionException, MojoFailureException {
98109
}
99110
}
100111

101-
/** Avoid dangling containers if the build is interrupted (e.g. via Ctrl+C) before the StopContainer mojo runs. */
102-
private void addShutdownHookToCleanUpContainers()
103-
{
112+
/**
113+
* Avoid dangling containers if the build is interrupted (e.g. via Ctrl+C) before the StopContainer mojo runs.
114+
*/
115+
private void addShutdownHookToCleanUpContainers() {
104116
getLog().info("Started containers will be forcibly cleaned up when the build finishes");
105-
Runtime.getRuntime().addShutdownHook(new Thread(new Runnable()
106-
{
117+
Runtime.getRuntime().addShutdownHook(new Thread(new Runnable() {
107118
@Override
108-
public void run()
109-
{
119+
public void run() {
110120
cleanUpStartedContainers();
111121
}
112122
}));
@@ -193,13 +203,39 @@ private boolean hasDuplicateIds() {
193203

194204
private void exposePortsToProject(ContainerStartConfiguration configuration, List<ExposedPort> exposedPorts) {
195205
exposedPorts.parallelStream().forEach(port -> {
196-
String prefix = String.format("docker.containers.%s.ports.%s.",
197-
configuration.getId(), port.getContainerPort());
206+
String prefix = String.format("docker.containers.%s.ports.%s.", configuration.getId(), port.getContainerPort());
198207
addPropertyToProject(prefix + "host", port.getHost());
199208
addPropertyToProject(prefix + "port", String.valueOf(port.getExternalPort()));
200209
});
201210
}
202211

212+
private void generateMappingsFile() throws MojoExecutionException {
213+
try {
214+
if (dockerMappingsFile.getParentFile() != null) {
215+
Files.createDirectories(dockerMappingsFile.getParentFile().toPath());
216+
}
217+
Files.createFile(dockerMappingsFile.toPath());
218+
addPropertyToProject("docker.mappings.file", dockerMappingsFile.getAbsolutePath());
219+
} catch (IOException e) {
220+
throw new MojoExecutionException("Error generating docker mapping file: ", e);
221+
}
222+
}
223+
224+
private void writeListOfPortsToFile(ContainerStartConfiguration configuration, List<ExposedPort> exposedPorts) throws MojoExecutionException {
225+
try (BufferedWriter writer = Files.newBufferedWriter(dockerMappingsFile.toPath(), APPEND)) {
226+
getLog().info(String.format("Writing properties for container '%s' to '%s'", configuration.getId(), dockerMappingsFile.getName()));
227+
for (ExposedPort port : exposedPorts) {
228+
String prefix = String.format("docker.containers.%s.ports.%s.", configuration.getId(), port.getContainerPort());
229+
writer.write(prefix + "host=" + port.getHost());
230+
writer.newLine();
231+
writer.write(prefix + "port=" + String.valueOf(port.getExternalPort()));
232+
writer.newLine();
233+
}
234+
} catch (IOException e) {
235+
throw new MojoExecutionException("Error writing to docker mapping file: ", e);
236+
}
237+
}
238+
203239
private void replaceImageWithBuiltImageIdIfInternalId(ContainerStartConfiguration configuration) {
204240
Optional<BuiltImageInfo> builtImage = getBuiltImageForStartId(configuration.getImage());
205241
if (builtImage.isPresent()) {
@@ -227,6 +263,10 @@ public void setMojoExecution(final MojoExecution mojoExecution) {
227263
this.mojoExecution = mojoExecution;
228264
}
229265

266+
public void setDockerMappingsFile(File dockerMappingsFile) {
267+
this.dockerMappingsFile = dockerMappingsFile;
268+
}
269+
230270
private void addPropertyToProject(String key, String value) {
231271
getLog().info(String.format("Setting property '%s' to '%s'", key, value));
232272
project.getProperties().setProperty(key, value);

src/test/java/net/wouterdanes/docker/maven/StartContainerMojoTest.java

Lines changed: 32 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -28,14 +28,20 @@
2828
import org.apache.maven.plugin.MojoExecution;
2929
import org.apache.maven.project.MavenProject;
3030
import org.junit.After;
31+
import org.junit.Assert;
3132
import org.junit.Before;
3233
import org.junit.Test;
3334
import org.mockito.ArgumentCaptor;
3435
import org.mockito.Matchers;
3536
import org.mockito.invocation.InvocationOnMock;
3637
import org.mockito.stubbing.Answer;
3738

39+
import java.io.File;
40+
import java.io.IOException;
41+
import java.nio.file.Files;
42+
import java.nio.file.Paths;
3843
import java.util.*;
44+
import java.util.stream.Stream;
3945

4046
import static org.junit.Assert.assertEquals;
4147
import static org.junit.Assert.assertNotNull;
@@ -45,6 +51,7 @@
4551
public class StartContainerMojoTest {
4652

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

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

7482
@Test
@@ -285,8 +293,8 @@ public void testThatContainerWaitsForLinkedContainerToStart() throws Exception {
285293
final ContainerStartConfiguration parent = new ContainerStartConfiguration()
286294
.withId("parent")
287295
.withLink(new ContainerLink()
288-
.toContainer("linked")
289-
.withAlias("database")
296+
.toContainer("linked")
297+
.withAlias("database")
290298
);
291299

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

312320
@Test
313321
public void testThatMojoStartsAContainerOnTheProviderWithEnvironmentVariables() throws Exception {
314-
Map<String, String> env = new HashMap<>();
315-
env.put("TEST_KEY", "test value");
316-
322+
Map<String, String> env = new HashMap<>();
323+
env.put("TEST_KEY", "test value");
324+
317325
ContainerStartConfiguration startConfiguration = new ContainerStartConfiguration()
318-
.withEnv(env);
326+
.withEnv(env);
319327
StartContainerMojo mojo = createMojo(startConfiguration);
320328

321329
mojo.execute();
322-
330+
323331
ArgumentCaptor<ContainerStartConfiguration> captor = ArgumentCaptor.forClass(ContainerStartConfiguration.class);
324332
verify(FakeDockerProvider.instance).startContainer(captor.capture());
325333

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

372+
@Test
373+
public void testThatDockerMappingsFileIsCreated() throws Exception {
374+
ContainerStartConfiguration startConfiguration = new ContainerStartConfiguration();
375+
StartContainerMojo mojo = createMojo(startConfiguration);
376+
377+
File dockerMappingsFile = new File(DOCKER_MAPPINGS_FILE);
378+
379+
assertEquals(dockerMappingsFile.exists(), false);
380+
381+
mojo.execute();
382+
383+
verify(FakeDockerProvider.instance).startContainer(startConfiguration);
384+
385+
assertEquals(dockerMappingsFile.exists(), true);
386+
}
387+
364388
private StartContainerMojo createMojo(final ContainerStartConfiguration startConfiguration) {
365389
return createMojo(startConfiguration, FAKE_PROVIDER_KEY);
366390
}
@@ -375,6 +399,7 @@ private StartContainerMojo createMojo(List<ContainerStartConfiguration> startCon
375399
mojo.setProviderName(provider);
376400
mojo.setPluginContext(new HashMap());
377401
mojo.setMojoExecution(mojoExecution);
402+
mojo.setDockerMappingsFile(new File(DOCKER_MAPPINGS_FILE));
378403

379404
return mojo;
380405
}

0 commit comments

Comments
 (0)