Skip to content

Commit 6634cf7

Browse files
committed
Allow running under root on Linux when unshare is available
1 parent 5917444 commit 6634cf7

File tree

4 files changed

+71
-39
lines changed

4 files changed

+71
-39
lines changed

.github/workflows/maven.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ jobs:
66
runs-on: ubuntu-latest
77
strategy:
88
matrix:
9-
java: [8, 11, 13]
9+
java: [8, 11, 13, 14]
1010
steps:
1111
- name: Checkout project
1212
uses: actions/checkout@v1

pom.xml

Lines changed: 16 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -109,12 +109,12 @@
109109
<dependency>
110110
<groupId>org.apache.commons</groupId>
111111
<artifactId>commons-lang3</artifactId>
112-
<version>3.6</version>
112+
<version>3.10</version>
113113
</dependency>
114114
<dependency>
115115
<groupId>org.apache.commons</groupId>
116116
<artifactId>commons-compress</artifactId>
117-
<version>1.19</version>
117+
<version>1.20</version>
118118
</dependency>
119119
<dependency>
120120
<groupId>org.tukaani</groupId>
@@ -124,29 +124,29 @@
124124
<dependency>
125125
<groupId>commons-io</groupId>
126126
<artifactId>commons-io</artifactId>
127-
<version>2.6</version>
127+
<version>2.7</version>
128128
</dependency>
129129
<dependency>
130130
<groupId>commons-codec</groupId>
131131
<artifactId>commons-codec</artifactId>
132-
<version>1.11</version>
132+
<version>1.14</version>
133133
</dependency>
134134
<dependency>
135135
<groupId>org.flywaydb</groupId>
136136
<artifactId>flyway-core</artifactId>
137-
<version>6.0.8</version>
137+
<version>6.5.1</version>
138138
<optional>true</optional>
139139
</dependency>
140140
<dependency>
141141
<groupId>org.liquibase</groupId>
142142
<artifactId>liquibase-core</artifactId>
143-
<version>3.6.3</version>
143+
<version>4.0.0</version>
144144
<optional>true</optional>
145145
</dependency>
146146
<dependency>
147147
<groupId>org.postgresql</groupId>
148148
<artifactId>postgresql</artifactId>
149-
<version>42.2.5</version>
149+
<version>42.2.14</version>
150150
</dependency>
151151
<dependency>
152152
<groupId>junit</groupId>
@@ -158,21 +158,21 @@
158158
<dependency>
159159
<groupId>org.junit.jupiter</groupId>
160160
<artifactId>junit-jupiter-api</artifactId>
161-
<version>5.3.2</version>
161+
<version>5.6.2</version>
162162
<scope>provided</scope>
163163
<optional>true</optional>
164164
</dependency>
165165

166166
<dependency>
167167
<groupId>org.slf4j</groupId>
168168
<artifactId>slf4j-simple</artifactId>
169-
<version>1.7.25</version>
169+
<version>1.7.30</version>
170170
<scope>test</scope>
171171
</dependency>
172172
<dependency>
173173
<groupId>org.mockito</groupId>
174174
<artifactId>mockito-core</artifactId>
175-
<version>2.13.0</version>
175+
<version>3.4.0</version>
176176
<scope>test</scope>
177177
</dependency>
178178
</dependencies>
@@ -181,7 +181,7 @@
181181
<plugins>
182182
<plugin>
183183
<artifactId>maven-pmd-plugin</artifactId>
184-
<version>3.8</version>
184+
<version>3.13.0</version>
185185
<executions>
186186
<execution>
187187
<phase>verify</phase>
@@ -194,13 +194,13 @@
194194
<dependency>
195195
<groupId>net.sourceforge.pmd</groupId>
196196
<artifactId>pmd-core</artifactId>
197-
<version>5.6.1</version>
197+
<version>6.25.0</version>
198198
<scope>compile</scope>
199199
</dependency>
200200
<dependency>
201201
<groupId>net.sourceforge.pmd</groupId>
202202
<artifactId>pmd-java</artifactId>
203-
<version>5.6.1</version>
203+
<version>6.25.0</version>
204204
<scope>compile</scope>
205205
</dependency>
206206
</dependencies>
@@ -216,7 +216,7 @@
216216
<plugin>
217217
<groupId>org.apache.maven.plugins</groupId>
218218
<artifactId>maven-source-plugin</artifactId>
219-
<version>3.0.1</version>
219+
<version>3.2.1</version>
220220
<executions>
221221
<execution>
222222
<id>attach-sources</id>
@@ -229,7 +229,7 @@
229229
<plugin>
230230
<groupId>org.apache.maven.plugins</groupId>
231231
<artifactId>maven-javadoc-plugin</artifactId>
232-
<version>2.10.4</version>
232+
<version>3.2.0</version>
233233
<executions>
234234
<execution>
235235
<id>attach-javadocs</id>
@@ -263,7 +263,7 @@
263263
<plugin>
264264
<groupId>org.apache.maven.plugins</groupId>
265265
<artifactId>maven-gpg-plugin</artifactId>
266-
<version>1.5</version>
266+
<version>1.6</version>
267267
<executions>
268268
<execution>
269269
<id>sign-artifacts</id>

src/main/java/io/zonky/test/db/postgres/embedded/EmbeddedPostgres.java

Lines changed: 53 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -14,12 +14,7 @@
1414
package io.zonky.test.db.postgres.embedded;
1515

1616

17-
import java.io.ByteArrayInputStream;
18-
import java.io.Closeable;
19-
import java.io.File;
20-
import java.io.FileOutputStream;
21-
import java.io.IOException;
22-
import java.io.InputStream;
17+
import java.io.*;
2318
import java.net.InetAddress;
2419
import java.net.InetSocketAddress;
2520
import java.net.ServerSocket;
@@ -104,6 +99,7 @@ public class EmbeddedPostgres implements Closeable
10499
private volatile FileOutputStream lockStream;
105100
private volatile FileLock lock;
106101
private final boolean cleanDataDirectory;
102+
private boolean useUnshare = false;
107103

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

132+
if (SystemUtils.IS_OS_LINUX) {
133+
int uid = (int) new com.sun.security.auth.module.UnixSystem().getUid();
134+
if (uid == 0) {
135+
final List<String> command = new ArrayList<>();
136+
command.addAll(Arrays.asList(
137+
"unshare", "-U",
138+
"id", "-u"
139+
));
140+
final ProcessBuilder builder = new ProcessBuilder(command);
141+
final Process process = builder.start();
142+
BufferedReader br = new BufferedReader(new InputStreamReader(process.getInputStream()));
143+
try {
144+
process.waitFor();
145+
} catch (InterruptedException e) {
146+
throw new RuntimeException(e);
147+
}
148+
if (process.exitValue() == 0 && br.readLine() != "0") {
149+
useUnshare = true;
150+
}
151+
}
152+
}
153+
136154
if (parentDirectory != null) {
137155
mkdirs(parentDirectory);
138156
cleanOldDataDirectories(parentDirectory);
@@ -186,8 +204,8 @@ public DataSource getDatabase(String userName, String dbName) {
186204
public DataSource getDatabase(String userName, String dbName, Map<String, String> properties)
187205
{
188206
final PGSimpleDataSource ds = new PGSimpleDataSource();
189-
ds.setServerName("localhost");
190-
ds.setPortNumber(port);
207+
ds.setServerNames(new String[] {"localhost"});
208+
ds.setPortNumbers(new int[] {port});
191209
ds.setDatabaseName(dbName);
192210
ds.setUser(userName);
193211

@@ -243,10 +261,10 @@ private void initdb()
243261
watch.start();
244262
List<String> command = new ArrayList<>();
245263
command.addAll(Arrays.asList(
246-
pgBin("initdb"), "-A", "trust", "-U", PG_SUPERUSER,
264+
"-A", "trust", "-U", PG_SUPERUSER,
247265
"-D", dataDirectory.getPath(), "-E", "UTF-8"));
248266
command.addAll(createLocaleOptions());
249-
system(command.toArray(new String[command.size()]));
267+
system(pgBin("initdb"), command);
250268
LOG.info("{} initdb completed in {}", instanceId, watch);
251269
}
252270

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

261279
final List<String> args = new ArrayList<>();
280+
args.addAll(pgBin("postgres"));
262281
args.addAll(Arrays.asList(
263-
pgBin("pg_ctl"),
264-
"-D", dataDirectory.getPath(),
265-
"-o", createInitOptions().stream().collect(Collectors.joining(" ")),
266-
"-w",
267-
"start"
282+
"-D", dataDirectory.getPath()
268283
));
284+
args.addAll(createInitOptions());
269285

270286
final ProcessBuilder builder = new ProcessBuilder(args);
271287

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

277293
if (outputRedirector.type() == ProcessBuilder.Redirect.Type.PIPE) {
278-
ProcessOutputLogger.logOutput(LOG, postmaster, "pg_ctl");
294+
ProcessOutputLogger.logOutput(LOG, postmaster, "postgres");
279295
}
280296

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

415431
private void pgCtl(File dir, String action)
416432
{
417-
system(pgBin("pg_ctl"), "-D", dir.getPath(), action, "-m", PG_STOP_MODE, "-t", PG_STOP_WAIT_S, "-w");
433+
final List<String> args = new ArrayList<>();
434+
args.addAll(Arrays.asList(
435+
"-D", dir.getPath(), action,
436+
"-m", PG_STOP_MODE, "-t",
437+
PG_STOP_WAIT_S, "-w"
438+
));
439+
system(pgBin("pg_ctl"), args);
418440
}
419441

420442
private void cleanOldDataDirectories(File parentDirectory)
@@ -461,10 +483,17 @@ private void cleanOldDataDirectories(File parentDirectory)
461483
}
462484
}
463485

464-
private String pgBin(String binaryName)
486+
private List<String> pgBin(String binaryName)
465487
{
488+
final List<String> args = new ArrayList<>();
489+
if (useUnshare) {
490+
args.addAll(Arrays.asList(
491+
"unshare", "-U"
492+
));
493+
}
466494
final String extension = SystemUtils.IS_OS_WINDOWS ? ".exe" : "";
467-
return new File(pgDir, "bin/" + binaryName + extension).getPath();
495+
args.add(new File(pgDir, "bin/" + binaryName + extension).getPath());
496+
return args;
468497
}
469498

470499
private static File getWorkingDirectory()
@@ -614,8 +643,11 @@ public int hashCode() {
614643
}
615644
}
616645

617-
private void system(String... command)
646+
private void system(List<String> bin, List<String> args)
618647
{
648+
final List<String> command = new ArrayList<>();
649+
command.addAll(bin);
650+
command.addAll(args);
619651
try {
620652
final ProcessBuilder builder = new ProcessBuilder(command);
621653
builder.redirectErrorStream(true);
@@ -624,7 +656,7 @@ private void system(String... command)
624656
final Process process = builder.start();
625657

626658
if (outputRedirector.type() == ProcessBuilder.Redirect.Type.PIPE) {
627-
String processName = command[0].replaceAll("^.*[\\\\/](\\w+)(\\.exe)?$", "$1");
659+
String processName = bin.get(bin.size() - 1).replaceAll("^.*[\\\\/](\\w+)(\\.exe)?$", "$1");
628660
ProcessOutputLogger.logOutput(LOG, process, processName);
629661
}
630662
if (0 != process.waitFor()) {

src/main/java/io/zonky/test/db/postgres/embedded/PreparedDbProvider.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -123,7 +123,7 @@ public ConnectionInfo createNewDatabase() throws SQLException
123123
public DataSource createDataSourceFromConnectionInfo(final ConnectionInfo connectionInfo) throws SQLException
124124
{
125125
final PGSimpleDataSource ds = new PGSimpleDataSource();
126-
ds.setPortNumber(connectionInfo.getPort());
126+
ds.setPortNumbers(new int[] {connectionInfo.getPort()});
127127
ds.setDatabaseName(connectionInfo.getDbName());
128128
ds.setUser(connectionInfo.getUser());
129129

0 commit comments

Comments
 (0)