Skip to content

Commit

Permalink
Allow running under root on Linux when unshare is available
Browse files Browse the repository at this point in the history
  • Loading branch information
jameshilliard committed Jul 16, 2020
1 parent 5917444 commit 6634cf7
Show file tree
Hide file tree
Showing 4 changed files with 71 additions and 39 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/maven.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ jobs:
runs-on: ubuntu-latest
strategy:
matrix:
java: [8, 11, 13]
java: [8, 11, 13, 14]
steps:
- name: Checkout project
uses: actions/checkout@v1
Expand Down
32 changes: 16 additions & 16 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -109,12 +109,12 @@
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.6</version>
<version>3.10</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-compress</artifactId>
<version>1.19</version>
<version>1.20</version>
</dependency>
<dependency>
<groupId>org.tukaani</groupId>
Expand All @@ -124,29 +124,29 @@
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.6</version>
<version>2.7</version>
</dependency>
<dependency>
<groupId>commons-codec</groupId>
<artifactId>commons-codec</artifactId>
<version>1.11</version>
<version>1.14</version>
</dependency>
<dependency>
<groupId>org.flywaydb</groupId>
<artifactId>flyway-core</artifactId>
<version>6.0.8</version>
<version>6.5.1</version>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.liquibase</groupId>
<artifactId>liquibase-core</artifactId>
<version>3.6.3</version>
<version>4.0.0</version>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.postgresql</groupId>
<artifactId>postgresql</artifactId>
<version>42.2.5</version>
<version>42.2.14</version>
</dependency>
<dependency>
<groupId>junit</groupId>
Expand All @@ -158,21 +158,21 @@
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-api</artifactId>
<version>5.3.2</version>
<version>5.6.2</version>
<scope>provided</scope>
<optional>true</optional>
</dependency>

<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-simple</artifactId>
<version>1.7.25</version>
<version>1.7.30</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId>
<version>2.13.0</version>
<version>3.4.0</version>
<scope>test</scope>
</dependency>
</dependencies>
Expand All @@ -181,7 +181,7 @@
<plugins>
<plugin>
<artifactId>maven-pmd-plugin</artifactId>
<version>3.8</version>
<version>3.13.0</version>
<executions>
<execution>
<phase>verify</phase>
Expand All @@ -194,13 +194,13 @@
<dependency>
<groupId>net.sourceforge.pmd</groupId>
<artifactId>pmd-core</artifactId>
<version>5.6.1</version>
<version>6.25.0</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>net.sourceforge.pmd</groupId>
<artifactId>pmd-java</artifactId>
<version>5.6.1</version>
<version>6.25.0</version>
<scope>compile</scope>
</dependency>
</dependencies>
Expand All @@ -216,7 +216,7 @@
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-source-plugin</artifactId>
<version>3.0.1</version>
<version>3.2.1</version>
<executions>
<execution>
<id>attach-sources</id>
Expand All @@ -229,7 +229,7 @@
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-javadoc-plugin</artifactId>
<version>2.10.4</version>
<version>3.2.0</version>
<executions>
<execution>
<id>attach-javadocs</id>
Expand Down Expand Up @@ -263,7 +263,7 @@
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-gpg-plugin</artifactId>
<version>1.5</version>
<version>1.6</version>
<executions>
<execution>
<id>sign-artifacts</id>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,7 @@
package io.zonky.test.db.postgres.embedded;


import java.io.ByteArrayInputStream;
import java.io.Closeable;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.*;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.ServerSocket;
Expand Down Expand Up @@ -104,6 +99,7 @@ public class EmbeddedPostgres implements Closeable
private volatile FileOutputStream lockStream;
private volatile FileLock lock;
private final boolean cleanDataDirectory;
private boolean useUnshare = false;

private final ProcessBuilder.Redirect errorRedirector;
private final ProcessBuilder.Redirect outputRedirector;
Expand Down Expand Up @@ -133,6 +129,28 @@ public class EmbeddedPostgres implements Closeable
this.pgStartupWait = pgStartupWait;
Objects.requireNonNull(this.pgStartupWait, "Wait time cannot be null");

if (SystemUtils.IS_OS_LINUX) {
int uid = (int) new com.sun.security.auth.module.UnixSystem().getUid();
if (uid == 0) {
final List<String> command = new ArrayList<>();
command.addAll(Arrays.asList(
"unshare", "-U",
"id", "-u"
));
final ProcessBuilder builder = new ProcessBuilder(command);
final Process process = builder.start();
BufferedReader br = new BufferedReader(new InputStreamReader(process.getInputStream()));
try {
process.waitFor();
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
if (process.exitValue() == 0 && br.readLine() != "0") {
useUnshare = true;
}
}
}

if (parentDirectory != null) {
mkdirs(parentDirectory);
cleanOldDataDirectories(parentDirectory);
Expand Down Expand Up @@ -186,8 +204,8 @@ public DataSource getDatabase(String userName, String dbName) {
public DataSource getDatabase(String userName, String dbName, Map<String, String> properties)
{
final PGSimpleDataSource ds = new PGSimpleDataSource();
ds.setServerName("localhost");
ds.setPortNumber(port);
ds.setServerNames(new String[] {"localhost"});
ds.setPortNumbers(new int[] {port});
ds.setDatabaseName(dbName);
ds.setUser(userName);

Expand Down Expand Up @@ -243,10 +261,10 @@ private void initdb()
watch.start();
List<String> command = new ArrayList<>();
command.addAll(Arrays.asList(
pgBin("initdb"), "-A", "trust", "-U", PG_SUPERUSER,
"-A", "trust", "-U", PG_SUPERUSER,
"-D", dataDirectory.getPath(), "-E", "UTF-8"));
command.addAll(createLocaleOptions());
system(command.toArray(new String[command.size()]));
system(pgBin("initdb"), command);
LOG.info("{} initdb completed in {}", instanceId, watch);
}

Expand All @@ -259,13 +277,11 @@ private void startPostmaster() throws IOException
}

final List<String> args = new ArrayList<>();
args.addAll(pgBin("postgres"));
args.addAll(Arrays.asList(
pgBin("pg_ctl"),
"-D", dataDirectory.getPath(),
"-o", createInitOptions().stream().collect(Collectors.joining(" ")),
"-w",
"start"
"-D", dataDirectory.getPath()
));
args.addAll(createInitOptions());

final ProcessBuilder builder = new ProcessBuilder(args);

Expand All @@ -275,7 +291,7 @@ private void startPostmaster() throws IOException
final Process postmaster = builder.start();

if (outputRedirector.type() == ProcessBuilder.Redirect.Type.PIPE) {
ProcessOutputLogger.logOutput(LOG, postmaster, "pg_ctl");
ProcessOutputLogger.logOutput(LOG, postmaster, "postgres");
}

LOG.info("{} postmaster started as {} on port {}. Waiting up to {} for server startup to finish.", instanceId, postmaster.toString(), port, pgStartupWait);
Expand Down Expand Up @@ -414,7 +430,13 @@ public void close() throws IOException

private void pgCtl(File dir, String action)
{
system(pgBin("pg_ctl"), "-D", dir.getPath(), action, "-m", PG_STOP_MODE, "-t", PG_STOP_WAIT_S, "-w");
final List<String> args = new ArrayList<>();
args.addAll(Arrays.asList(
"-D", dir.getPath(), action,
"-m", PG_STOP_MODE, "-t",
PG_STOP_WAIT_S, "-w"
));
system(pgBin("pg_ctl"), args);
}

private void cleanOldDataDirectories(File parentDirectory)
Expand Down Expand Up @@ -461,10 +483,17 @@ private void cleanOldDataDirectories(File parentDirectory)
}
}

private String pgBin(String binaryName)
private List<String> pgBin(String binaryName)
{
final List<String> args = new ArrayList<>();
if (useUnshare) {
args.addAll(Arrays.asList(
"unshare", "-U"
));
}
final String extension = SystemUtils.IS_OS_WINDOWS ? ".exe" : "";
return new File(pgDir, "bin/" + binaryName + extension).getPath();
args.add(new File(pgDir, "bin/" + binaryName + extension).getPath());
return args;
}

private static File getWorkingDirectory()
Expand Down Expand Up @@ -614,8 +643,11 @@ public int hashCode() {
}
}

private void system(String... command)
private void system(List<String> bin, List<String> args)
{
final List<String> command = new ArrayList<>();
command.addAll(bin);
command.addAll(args);
try {
final ProcessBuilder builder = new ProcessBuilder(command);
builder.redirectErrorStream(true);
Expand All @@ -624,7 +656,7 @@ private void system(String... command)
final Process process = builder.start();

if (outputRedirector.type() == ProcessBuilder.Redirect.Type.PIPE) {
String processName = command[0].replaceAll("^.*[\\\\/](\\w+)(\\.exe)?$", "$1");
String processName = bin.get(bin.size() - 1).replaceAll("^.*[\\\\/](\\w+)(\\.exe)?$", "$1");
ProcessOutputLogger.logOutput(LOG, process, processName);
}
if (0 != process.waitFor()) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,7 @@ public ConnectionInfo createNewDatabase() throws SQLException
public DataSource createDataSourceFromConnectionInfo(final ConnectionInfo connectionInfo) throws SQLException
{
final PGSimpleDataSource ds = new PGSimpleDataSource();
ds.setPortNumber(connectionInfo.getPort());
ds.setPortNumbers(new int[] {connectionInfo.getPort()});
ds.setDatabaseName(connectionInfo.getDbName());
ds.setUser(connectionInfo.getUser());

Expand Down

0 comments on commit 6634cf7

Please sign in to comment.