Skip to content

Commit 8d440d6

Browse files
committed
Automated container feature enabling
1 parent ec85f11 commit 8d440d6

File tree

7 files changed

+95
-42
lines changed

7 files changed

+95
-42
lines changed

.idea/AndroidProjectSystem.xml

Lines changed: 6 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

.idea/gradle.xml

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

.idea/vcs.xml

Lines changed: 0 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

.idea/workspace.xml

Lines changed: 23 additions & 25 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

build.gradle

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,4 +27,8 @@ dependencies {
2727
implementation "org.apache.commons:commons-compress:1.24.0"
2828
implementation "org.slf4j:slf4j-simple:2.0.7"
2929
testImplementation "org.junit.jupiter:junit-jupiter:5.10.1"
30+
}
31+
32+
test {
33+
useJUnitPlatform()
3034
}

src/main/java/io/github/intisy/docker/WindowsDockerProvider.java

Lines changed: 50 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,7 @@
66
import com.github.dockerjava.httpclient5.ApacheDockerHttpClient;
77
import com.github.dockerjava.transport.DockerHttpClient;
88

9-
import java.io.File;
10-
import java.io.IOException;
11-
import java.io.InputStream;
9+
import java.io.*;
1210
import java.net.HttpURLConnection;
1311
import java.net.URL;
1412
import java.nio.file.Files;
@@ -105,6 +103,13 @@ private void downloadAndExtract(String urlString) throws IOException {
105103

106104
@Override
107105
public void start() throws IOException, InterruptedException {
106+
if (!isAdministrator()) {
107+
System.err.println("\nERROR: Docker daemon on Windows requires Administrator privileges.\nPlease run your application or test as Administrator.\n");
108+
throw new RuntimeException("Administrator privileges required to start Docker daemon on Windows.");
109+
}
110+
111+
ensureContainersFeatureEnabled();
112+
108113
this.dockerClient = tryConnectToExistingDocker();
109114
if (this.dockerClient != null) {
110115
return;
@@ -123,15 +128,50 @@ public void start() throws IOException, InterruptedException {
123128
}
124129
}
125130

126-
private DockerClient tryConnectToExistingDocker() {
127-
String systemPipePath = "//./pipe/docker_engine";
128-
File systemPipe = new File(systemPipePath);
131+
private void ensureContainersFeatureEnabled() throws IOException, InterruptedException {
132+
ProcessBuilder pb = new ProcessBuilder("powershell.exe", "-Command", "Get-WindowsOptionalFeature -Online -FeatureName Containers");
133+
pb.redirectErrorStream(true);
134+
Process process = pb.start();
135+
136+
StringBuilder output = new StringBuilder();
137+
try (BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()))) {
138+
String line;
139+
while ((line = reader.readLine()) != null) {
140+
output.append(line).append("\n");
141+
}
142+
}
143+
144+
process.waitFor();
145+
String outputStr = output.toString();
146+
147+
if (!outputStr.contains("State : Enabled")) {
148+
System.out.println("Enabling Windows Containers feature (requires reboot)...");
149+
ProcessBuilder enablePb = new ProcessBuilder("powershell.exe", "-Command", "Enable-WindowsOptionalFeature -Online -FeatureName Containers -All");
150+
enablePb.inheritIO();
151+
Process enableProcess = enablePb.start();
152+
enableProcess.waitFor();
153+
System.err.println("\nThe Windows Containers feature was just enabled. Please reboot your computer and run again.\n");
154+
throw new RuntimeException("Windows Containers feature enabled. Reboot required.");
155+
}
156+
}
157+
158+
private boolean isAdministrator() {
159+
try {
160+
ProcessBuilder pb = new ProcessBuilder("net", "session");
161+
pb.redirectErrorStream(true);
162+
Process process = pb.start();
163+
return process.waitFor() == 0;
164+
} catch (IOException | InterruptedException e) {
165+
return false;
166+
}
167+
}
129168

130-
if (systemPipe.exists()) {
131-
System.out.println("Found existing Docker pipe at " + systemPipePath + ". Attempting to connect.");
169+
private DockerClient tryConnectToExistingDocker() {
170+
if (Files.exists(DOCKER_PIPE_PATH)) {
171+
System.out.println("Found existing Docker pipe at " + DOCKER_PIPE_PATH + ". Attempting to connect.");
132172
try {
133173
DefaultDockerClientConfig config = DefaultDockerClientConfig.createDefaultConfigBuilder()
134-
.withDockerHost("npipe://" + systemPipePath).build();
174+
.withDockerHost("npipe://" + DOCKER_PIPE_PATH.toString().replace("\\", "/")).build();
135175

136176
DockerHttpClient httpClient = new ApacheDockerHttpClient.Builder()
137177
.dockerHost(config.getDockerHost())
@@ -143,7 +183,7 @@ private DockerClient tryConnectToExistingDocker() {
143183
System.out.println("Successfully connected to existing Docker daemon.");
144184
return client;
145185
} catch (Exception e) {
146-
System.err.println("Failed to connect to existing Docker daemon at " + systemPipePath + ": " + e.getMessage());
186+
System.err.println("Failed to connect to existing Docker daemon at " + DOCKER_PIPE_PATH + ": " + e.getMessage());
147187
}
148188
}
149189
return null;

src/test/java/io/github/intisy/docker/ContainerTest.java

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
import com.github.dockerjava.api.model.ExposedPort;
88
import com.github.dockerjava.api.model.HostConfig;
99
import com.github.dockerjava.api.model.Ports;
10+
import org.junit.jupiter.api.Test;
1011

1112
import java.util.concurrent.TimeUnit;
1213

@@ -89,17 +90,22 @@ public void shutdown() {
8990
}
9091

9192
public static void main(String[] args) {
92-
System.out.println("Starting container test on OS: " + System.getProperty("os.name"));
9393
ContainerTest test = new ContainerTest();
94+
test.start();
95+
}
96+
97+
@Test
98+
public void start() {
99+
System.out.println("Starting container test on OS: " + System.getProperty("os.name"));
94100
try {
95-
test.initialize();
96-
test.pullAndRunContainer("nginx:alpine", 80);
101+
initialize();
102+
pullAndRunContainer("nginx:alpine", 80);
97103
System.out.println("Container started successfully. The application will now shut down.");
98-
Runtime.getRuntime().addShutdownHook(new Thread(test::shutdown));
104+
Runtime.getRuntime().addShutdownHook(new Thread(this::shutdown));
99105

100106
} catch (Exception e) {
101107
System.err.println("A critical error occurred:");
102-
test.shutdown();
108+
shutdown();
103109
throw new RuntimeException(e);
104110
}
105111
}

0 commit comments

Comments
 (0)