Use slf4j

This commit is contained in:
Minecon724 2025-02-14 19:57:45 +01:00
commit 901e18c307
No known key found for this signature in database
GPG key ID: 3CCC4D267742C8E8
8 changed files with 130 additions and 35 deletions

67
pom.xml
View file

@ -11,7 +11,9 @@
<properties>
<maven.compiler.source>21</maven.compiler.source>
<maven.compiler.target>21</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<exec.mainClass>eu.m724.Main</exec.mainClass>
</properties>
<dependencies>
@ -20,6 +22,71 @@
<artifactId>json</artifactId>
<version>20250107</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>2.0.16</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-simple</artifactId>
<version>2.0.16</version>
</dependency>
<dependency>
<groupId>org.jetbrains</groupId>
<artifactId>annotations</artifactId>
<version>26.0.1</version>
<scope>compile</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>3.4.2</version>
<configuration>
<archive>
<manifest>
<addClasspath>true</addClasspath>
<mainClass>${exec.mainClass}</mainClass>
</manifest>
</archive>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>3.6.0</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
<configuration>
<minimizeJar>true</minimizeJar>
<createDependencyReducedPom>false</createDependencyReducedPom>
<shadedArtifactAttached>true</shadedArtifactAttached>
<filters>
<filter>
<artifact>*:*</artifact>
<excludes>
<exclude>META-INF/*.SF</exclude>
<exclude>META-INF/*.DSA</exclude>
<exclude>META-INF/*.RSA</exclude>
</excludes>
</filter>
</filters>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>

View file

@ -4,6 +4,8 @@ import eu.m724.docker.DockerEngine;
import eu.m724.docker.exception.FailedRequestException;
import eu.m724.docker.proxy.TcpSocketProxy;
import org.json.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.IOException;
import java.net.StandardProtocolFamily;
@ -11,29 +13,30 @@ import java.net.UnixDomainSocketAddress;
import java.util.concurrent.ExecutionException;
public class Main {
private static final Logger LOGGER = LoggerFactory.getLogger(Main.class);
public static void main(String[] args) throws IOException, InterruptedException {
var proxy = new TcpSocketProxy(StandardProtocolFamily.UNIX, UnixDomainSocketAddress.of("/var/run/docker.sock"));
proxy.start();
System.out.println("Started");
System.out.printf("Tested in %d ms %n", proxy.test() / 1000000);
LOGGER.info("Latency to remote: {} ms", proxy.test() / 1000000);
var engine = new DockerEngine(proxy.getURI());
engine.ping().join();
var info = engine.info().join();
System.out.println("Docker runtime:");
System.out.println("- " + info.getString("ID"));
System.out.println("- " + info.getString("OSType") + " " + info.getString("Architecture"));
System.out.println("- OS: " + info.getString("OperatingSystem") + " " + info.getString("OSVersion"));
System.out.println("- Hostname: " + info.getString("Name"));
LOGGER.info("Docker runtime:");
LOGGER.info("- {}", info.getString("ID"));
LOGGER.info("- {}, {}", info.getString("OSType"), info.getString("Architecture"));
LOGGER.info("- OS: {} version {}", info.getString("OperatingSystem"), info.getString("OSVersion"));
LOGGER.info("- Hostname: {}", info.getString("Name"));
JSONObject containerInfo = null;
try {
containerInfo = engine.inspectContainer("dcdn_nginx").get();
} catch (ExecutionException e) {
if (e.getCause() instanceof FailedRequestException fre && fre.getResponse().statusCode() == 404) {
System.out.println("Container doesn't exist");
LOGGER.info("Container doesn't exist");
} else {
throw new RuntimeException("Exception getting container info", e);
}
@ -41,14 +44,14 @@ public class Main {
if (containerInfo != null) {
var mounts = containerInfo.getJSONArray("Mounts");
System.out.printf("Detected %d mounts:%n", mounts.length());
LOGGER.debug("Detected {} mounts:", mounts.length());
for (int i=0; i<mounts.length(); i++) {
var j = mounts.getJSONObject(i);
System.out.printf("%s %s -> %s %n", j.getString("Name"), j.getString("Source"), j.getString("Destination"));
LOGGER.debug("{} {} -> {}", j.getString("Name"), j.getString("Source"), j.getString("Destination"));
}
} else {
System.out.println("Creating it");
LOGGER.info("Creating it");
var data = new JSONObject()
.put("Image", "nginx:1.27");

View file

@ -3,6 +3,8 @@ package eu.m724.docker;
import org.json.JSONObject;
import java.net.URI;
import java.net.http.HttpClient;
import java.time.Duration;
import java.util.Map;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.CompletionException;
@ -12,7 +14,7 @@ public class DockerEngine {
public DockerEngine(URI socketUri) {
this.dao = new DockerEngineDAO(socketUri);
this.dao = new DockerEngineDAO(socketUri, HttpClient.newBuilder().version(HttpClient.Version.HTTP_1_1).connectTimeout(Duration.ofSeconds(30)).build());
}
public CompletableFuture<Void> ping() {

View file

@ -1,31 +1,34 @@
package eu.m724.docker;
import eu.m724.docker.exception.FailedRequestException;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.json.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.net.URI;
import java.net.URLEncoder;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.time.Duration;
import java.nio.charset.StandardCharsets;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.CompletableFuture;
import java.util.stream.Collectors;
public class DockerEngineDAO {
private static final Logger LOGGER = LoggerFactory.getLogger(DockerEngineDAO.class);
private final URI socketUri;
private final HttpClient httpClient;
DockerEngineDAO(URI socketUri) {
DockerEngineDAO(URI socketUri, HttpClient httpClient) {
this.socketUri = socketUri;
this.httpClient = HttpClient.newBuilder().version(HttpClient.Version.HTTP_1_1).connectTimeout(Duration.ofSeconds(30)).build();
this.httpClient = httpClient;
}
public void close() {
httpClient.close();
}
/**
* Create a GET request that expects a JSON from the server.<br>
* A {@link FailedRequestException} is thrown by the future if a non-200 status code is returned.
@ -172,19 +175,16 @@ public class DockerEngineDAO {
}
private HttpRequest createRequest(String path) {
return HttpRequest.newBuilder(socketUri.resolve(path)).build();
}
private <T> CompletableFuture<T> commonRequest(@NotNull String path, @Nullable Map<String, Object> queryParams, @Nullable JSONObject data, @NotNull HttpResponse.BodyHandler<T> bodyHandler) {
Objects.requireNonNull(path, "Request path cannot be null");
Objects.requireNonNull(bodyHandler, "Body handler cannot be null");
private <T> CompletableFuture<T> commonRequest(String path, Map<String, Object> queryParams, JSONObject data, HttpResponse.BodyHandler<T> bodyHandler) {
if (queryParams != null && !queryParams.isEmpty()) {
path += '?';
path += queryParams.entrySet().stream()
.map(e -> e.getKey() + '=' + e.getValue())
.collect(Collectors.joining("&"));
path += encodeQueryParams(queryParams);
}
System.out.println(path);
LOGGER.debug("Calling request: {}", path);
var builder = HttpRequest.newBuilder(socketUri.resolve(path));
if (data != null) {
@ -200,4 +200,12 @@ public class DockerEngineDAO {
return response.body();
});
}
private String encodeQueryParams(@NotNull Map<String, Object> params) {
return params.entrySet().stream()
.map(e -> URLEncoder.encode(e.getKey(), StandardCharsets.UTF_8) +
"=" +
URLEncoder.encode(String.valueOf(e.getValue()), StandardCharsets.UTF_8))
.collect(Collectors.joining("&", "?", ""));
}
}

View file

@ -12,7 +12,7 @@ public class FailedRequestException extends CompletionException {
@Override
public String getMessage() {
return "Code: " + response.statusCode() + " | Body: " + response.body();
return "Request failed with status %d: %s".formatted(response.statusCode(), response.body());
}
public HttpResponse<?> getResponse() {

View file

@ -1,5 +1,8 @@
package eu.m724.docker.proxy;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.IOException;
import java.net.Socket;
import java.nio.ByteBuffer;
@ -13,6 +16,8 @@ public class ConnectionThread extends Thread {
private final RemoteSocketFactory remoteSocketFactory;
private final Socket clientSocket;
private final Logger LOGGER = LoggerFactory.getLogger(ConnectionThread.class);
ConnectionThread(ExecutorService executorService, RemoteSocketFactory remoteSocketFactory, Socket clientSocket) {
this.executorService = executorService;
this.remoteSocketFactory = remoteSocketFactory;
@ -25,11 +30,11 @@ public class ConnectionThread extends Thread {
clientSocket;
var remoteSocket = remoteSocketFactory.newChannel()
) {
System.out.println("connected");
LOGGER.debug("starting inner");
inner(remoteSocket);
System.out.println("disconnected");
LOGGER.debug("inner ended");
} catch (IOException e) {
System.err.println("Exception handling client: " + e.getMessage());
LOGGER.error("Exception handling client", e);
}
}

View file

@ -1,10 +1,15 @@
package eu.m724.docker.proxy;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.IOException;
import java.net.ServerSocket;
import java.util.concurrent.ExecutorService;
public class ServerRunnable implements Runnable {
private static final Logger LOGGER = LoggerFactory.getLogger(ServerRunnable.class);
private final ExecutorService executorService;
private final ServerSocket serverSocket;
private final RemoteSocketFactory remoteSocketFactory;
@ -26,7 +31,7 @@ public class ServerRunnable implements Runnable {
} catch (IOException e) {
if (serverSocket.isClosed()) break;
System.err.println("Exception handling client request: " + e.getMessage());
LOGGER.error("Exception handling client request", e);
}
}
}

View file

@ -1,11 +1,16 @@
package eu.m724.docker.proxy;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.IOException;
import java.net.*;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class TcpSocketProxy implements AutoCloseable {
private static final Logger LOGGER = LoggerFactory.getLogger(TcpSocketProxy.class);
private final RemoteSocketFactory remoteSocketFactory;
private ServerSocket serverSocket;
@ -28,7 +33,7 @@ public class TcpSocketProxy implements AutoCloseable {
this.executorService = Executors.newVirtualThreadPerTaskExecutor();
executorService.execute(new ServerRunnable(executorService, serverSocket, remoteSocketFactory));
System.out.println("Proxy bound on " + getURI());
LOGGER.info("Proxy bound on {}", getURI());
}
public long test() throws IOException {