Added health endpoint

This commit is contained in:
litoral05
2026-05-06 11:16:12 +01:00
parent 329dbab037
commit 0ac9f29ee0
4 changed files with 155 additions and 0 deletions
@@ -0,0 +1,21 @@
package com.litoralregas.openvpn.health;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/api/health")
public class HealthController {
private final OpenVpnHealthService openVpnHealthService;
public HealthController(OpenVpnHealthService openVpnHealthService) {
this.openVpnHealthService = openVpnHealthService;
}
@GetMapping("/openvpn")
public OpenVpnHealthResponse getOpenVpnHealth() {
return openVpnHealthService.checkHealth();
}
}
@@ -0,0 +1,9 @@
package com.litoralregas.openvpn.health;
import java.util.List;
public record OpenVpnHealthResponse(
String status,
List<OpenVpnServerHealth> servers
) {
}
@@ -0,0 +1,114 @@
package com.litoralregas.openvpn.health;
import com.litoralregas.openvpn.ssh.SshCommandResult;
import com.litoralregas.openvpn.ssh.SshService;
import org.springframework.stereotype.Service;
import java.time.Instant;
import java.util.List;
@Service
public class OpenVpnHealthService {
private final SshService sshService;
public OpenVpnHealthService(SshService sshService) {
this.sshService = sshService;
}
public OpenVpnHealthResponse checkHealth() {
OpenVpnServerHealth serverHealth = checkConfiguredVps();
String overallStatus;
if (!serverHealth.reachable()) {
overallStatus = "OFFLINE";
} else if (!serverHealth.openvpnServiceActive()) {
overallStatus = "DEGRADED";
} else {
overallStatus = "ONLINE";
}
return new OpenVpnHealthResponse(
overallStatus,
List.of(serverHealth)
);
}
private OpenVpnServerHealth checkConfiguredVps() {
String checkedAt = Instant.now().toString();
SshCommandResult serviceResult = sshService.executeOnConfiguredVps(
"""
if systemctl is-active --quiet openvpn-server@server; then
echo ACTIVE
elif systemctl is-active --quiet openvpn@server; then
echo ACTIVE
elif systemctl is-active --quiet openvpn; then
echo ACTIVE
else
echo INACTIVE
systemctl list-units --type=service --all | grep -i openvpn || true
fi
"""
);
boolean reachable = serviceResult.exitCode() != -1;
boolean active = serviceResult.stdout().contains("ACTIVE");
Integer activeClients = null;
if (reachable && active) {
activeClients = getActiveClientCount();
}
String error = null;
if (!reachable) {
error = serviceResult.stderr();
} else if (!active) {
error = cleanOutput(serviceResult.stdout() + "\n" + serviceResult.stderr());
}
return new OpenVpnServerHealth(
"Configured VPS",
reachable,
active,
activeClients,
checkedAt,
error
);
}
private Integer getActiveClientCount() {
SshCommandResult result = sshService.executeOnConfiguredVps(
"""
if [ -f /var/log/openvpn/status.log ]; then
grep -A 100 "Common Name" /var/log/openvpn/status.log | grep -v "Common Name" | grep -v "ROUTING TABLE" | grep -v "GLOBAL STATS" | grep -v "^$" | wc -l
elif [ -f /run/openvpn-server/status-server.log ]; then
grep -A 100 "Common Name" /run/openvpn-server/status-server.log | grep -v "Common Name" | grep -v "ROUTING TABLE" | grep -v "GLOBAL STATS" | grep -v "^$" | wc -l
else
echo 0
fi
"""
);
if (result.exitCode() != 0) {
return null;
}
try {
return Integer.parseInt(result.stdout().trim());
} catch (NumberFormatException e) {
return null;
}
}
private String cleanOutput(String value) {
if (value == null || value.isBlank()) {
return null;
}
return value.trim();
}
}
@@ -0,0 +1,11 @@
package com.litoralregas.openvpn.health;
public record OpenVpnServerHealth(
String name,
boolean reachable,
boolean openvpnServiceActive,
Integer activeClients,
String checkedAt,
String error
) {
}