Skip to content

Commit

Permalink
add container arguments to specify SELinux contexts for mounts (#334)
Browse files Browse the repository at this point in the history
* add container arguments to specify SELinux contexts for mounts
* remove unused import in test
* address review requests comments for formatting, lombok annotations, and clarity around SELinux
  • Loading branch information
josh-cain authored and rnorth committed Jun 21, 2017
1 parent 6411ce5 commit 7af0dc5
Show file tree
Hide file tree
Showing 4 changed files with 78 additions and 8 deletions.
36 changes: 32 additions & 4 deletions core/src/main/java/org/testcontainers/containers/Container.java
Original file line number Diff line number Diff line change
Expand Up @@ -80,11 +80,24 @@ public String getStderr() {
* Adds a file system binding. Consider using {@link #withFileSystemBind(String, String, BindMode)}
* for building a container in a fluent style.
*
* @param hostPath the file system path on the host
* @param hostPath the file system path on the host
* @param containerPath the file system path inside the container
* @param mode the bind mode
* @param mode the bind mode
*/
default void addFileSystemBind(final String hostPath, final String containerPath, final BindMode mode) {
addFileSystemBind(hostPath, containerPath, mode, SelinuxContext.NONE);
}

/**
* Adds a file system binding. Consider using {@link #withFileSystemBind(String, String, BindMode)}
* for building a container in a fluent style.
*
* @param hostPath the file system path on the host
* @param containerPath the file system path inside the container
* @param mode the bind mode
* @param selinuxContext selinux context argument to use for this file
*/
void addFileSystemBind(String hostPath, String containerPath, BindMode mode);
void addFileSystemBind(String hostPath, String containerPath, BindMode mode, SelinuxContext selinuxContext);

/**
* Add a link to another container.
Expand Down Expand Up @@ -205,7 +218,22 @@ public String getStderr() {
* @param mode access mode for the file
* @return this
*/
SELF withClasspathResourceMapping(String resourcePath, String containerPath, BindMode mode);
default SELF withClasspathResourceMapping(final String resourcePath, final String containerPath, final BindMode mode) {
withClasspathResourceMapping(resourcePath, containerPath, mode, SelinuxContext.NONE);
return self();
}

/**
* Map a resource (file or directory) on the classpath to a path inside the container.
* This will only work if you are running your tests outside a Docker container.
*
* @param resourcePath path to the resource on the classpath (relative to the classpath root; should not start with a leading slash)
* @param containerPath path this should be mapped to inside the container
* @param mode access mode for the file
* @param selinuxContext selinux context argument to use for this file
* @return this
*/
SELF withClasspathResourceMapping(String resourcePath, String containerPath, BindMode mode, SelinuxContext selinuxContext);

/**
* Set the duration of waiting time until container treated as started.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -485,10 +485,10 @@ public void addEnv(String key, String value) {
* {@inheritDoc}
*/
@Override
public void addFileSystemBind(String hostPath, String containerPath, BindMode mode) {
public void addFileSystemBind(final String hostPath, final String containerPath, final BindMode mode, final SelinuxContext selinuxContext) {

final MountableFile mountableFile = MountableFile.forHostPath(hostPath);
binds.add(new Bind(mountableFile.getResolvedPath(), new Volume(containerPath), mode.accessMode));
binds.add(new Bind(mountableFile.getResolvedPath(), new Volume(containerPath), mode.accessMode, selinuxContext.selContext));
}

/**
Expand Down Expand Up @@ -619,10 +619,18 @@ public SELF withNetworkMode(String networkMode) {
* {@inheritDoc}
*/
@Override
public SELF withClasspathResourceMapping(String resourcePath, String containerPath, BindMode mode) {
public SELF withClasspathResourceMapping(final String resourcePath, final String containerPath, final BindMode mode) {
return withClasspathResourceMapping(resourcePath, containerPath, mode, SelinuxContext.NONE);
}

/**
* {@inheritDoc}
*/
@Override
public SELF withClasspathResourceMapping(final String resourcePath, final String containerPath, final BindMode mode, final SelinuxContext selinuxContext) {
final MountableFile mountableFile = MountableFile.forClasspathResource(resourcePath);

this.addFileSystemBind(mountableFile.getResolvedPath(), containerPath, mode);
this.addFileSystemBind(mountableFile.getResolvedPath(), containerPath, mode, selinuxContext);

return self();
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package org.testcontainers.containers;

import com.github.dockerjava.api.model.SELContext;
import lombok.AllArgsConstructor;

/**
* Possible contexts for use with SELinux
*/
@AllArgsConstructor
public enum SelinuxContext {
SHARED(SELContext.shared),
SINGLE(SELContext.single),
NONE(SELContext.none);

public final SELContext selContext;

}
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@

import static org.rnorth.visibleassertions.VisibleAssertions.*;
import static org.testcontainers.containers.BindMode.READ_ONLY;
import static org.testcontainers.containers.BindMode.READ_WRITE;
import static org.testcontainers.containers.SelinuxContext.SHARED;

/**
* Tests for GenericContainerRules
Expand Down Expand Up @@ -101,6 +103,15 @@ public static void setupContent() throws FileNotFoundException {
.withClasspathResourceMapping("mappable-resource/test-resource.txt", "/content.txt", READ_ONLY)
.withCommand("/bin/sh", "-c", "while true; do cat /content.txt | nc -l -p 80; done");

/**
* Map a file on the classpath to a file in the container, and then expose the content for testing.
*/
@ClassRule
public static GenericContainer alpineClasspathResourceSelinux = new GenericContainer("alpine:3.2")
.withExposedPorts(80)
.withClasspathResourceMapping("mappable-resource/test-resource.txt", "/content.txt", READ_WRITE, SHARED)
.withCommand("/bin/sh", "-c", "while true; do cat /content.txt | nc -l -p 80; done");

/**
* Create a container with an extra host entry and expose the content of /etc/hosts for testing.
*/
Expand Down Expand Up @@ -203,6 +214,12 @@ public void customClasspathResourceMappingTest() throws IOException {
assertEquals("Resource on the classpath can be mapped using calls to withClasspathResourceMapping", "FOOBAR", line);
}

@Test
public void customClasspathResourceMappingWithSelinuxTest() throws IOException {
String line = getReaderForContainerPort80(alpineClasspathResourceSelinux).readLine();
assertEquals("Resource on the classpath can be mapped using calls to withClasspathResourceMappingSelinux", "FOOBAR", line);
}

@Test
public void exceptionThrownWhenMappedPortNotFound() throws IOException {
assertThrows("When the requested port is not mapped, getMappedPort() throws an exception",
Expand Down

0 comments on commit 7af0dc5

Please sign in to comment.