diff --git a/pom.xml b/pom.xml
index d106cd4..7e55c70 100644
--- a/pom.xml
+++ b/pom.xml
@@ -65,6 +65,11 @@
spring-boot-starter-test
test
+
+ com.jcraft
+ jsch
+ 0.1.55
+
diff --git a/src/main/java/com/litoralregas/openvpn/router/RouterController.java b/src/main/java/com/litoralregas/openvpn/router/RouterController.java
index 8c751c1..66a4d2a 100644
--- a/src/main/java/com/litoralregas/openvpn/router/RouterController.java
+++ b/src/main/java/com/litoralregas/openvpn/router/RouterController.java
@@ -78,4 +78,34 @@ public class RouterController {
return DeploymentResponse.from(failedDeployment);
}
}
+
+ @PostMapping("/{id}/remove")
+ public DeploymentResponse remove(@PathVariable UUID id) {
+ Router router = service.findById(id);
+
+ var deployment = deploymentService.startDeployment(router, DeploymentAction.REMOVE);
+
+ try {
+ service.forceStatus(id, RouterStatus.PROVISIONING); // or REMOVING if you want later
+
+ // simulate removal
+ var finished = deploymentService.finishSuccess(
+ deployment,
+ "Removal completed successfully"
+ );
+
+ service.forceStatus(id, RouterStatus.REMOVED);
+
+ return DeploymentResponse.from(finished);
+ } catch (Exception e) {
+ var failed = deploymentService.finishFailure(
+ deployment,
+ e.getMessage()
+ );
+
+ service.forceStatus(id, RouterStatus.FAILED);
+
+ return DeploymentResponse.from(failed);
+ }
+ }
}
\ No newline at end of file
diff --git a/src/main/java/com/litoralregas/openvpn/ssh/SshCommandResult.java b/src/main/java/com/litoralregas/openvpn/ssh/SshCommandResult.java
new file mode 100644
index 0000000..432cb4c
--- /dev/null
+++ b/src/main/java/com/litoralregas/openvpn/ssh/SshCommandResult.java
@@ -0,0 +1,8 @@
+package com.litoralregas.openvpn.ssh;
+
+public record SshCommandResult(
+ int exitCode,
+ String stdout,
+ String stderr
+) {
+}
\ No newline at end of file
diff --git a/src/main/java/com/litoralregas/openvpn/ssh/SshService.java b/src/main/java/com/litoralregas/openvpn/ssh/SshService.java
new file mode 100644
index 0000000..9414d2e
--- /dev/null
+++ b/src/main/java/com/litoralregas/openvpn/ssh/SshService.java
@@ -0,0 +1,58 @@
+package com.litoralregas.openvpn.ssh;
+
+import com.jcraft.jsch.*;
+import org.springframework.stereotype.Service;
+
+import java.io.ByteArrayOutputStream;
+import java.nio.charset.StandardCharsets;
+
+@Service
+public class SshService {
+
+ public SshCommandResult execute(
+ String host,
+ int port,
+ String username,
+ String password,
+ String command
+ ) {
+ Session session = null;
+ ChannelExec channel = null;
+
+ try {
+ JSch jsch = new JSch();
+
+ session = jsch.getSession(username, host, port);
+ session.setPassword(password);
+ session.setConfig("StrictHostKeyChecking", "no");
+ session.connect(10_000);
+
+ channel = (ChannelExec) session.openChannel("exec");
+ channel.setCommand(command);
+
+ ByteArrayOutputStream stdout = new ByteArrayOutputStream();
+ ByteArrayOutputStream stderr = new ByteArrayOutputStream();
+
+ channel.setOutputStream(stdout);
+ channel.setErrStream(stderr);
+
+ channel.connect();
+
+ while (!channel.isClosed()) {
+ Thread.sleep(100);
+ }
+
+ return new SshCommandResult(
+ channel.getExitStatus(),
+ stdout.toString(StandardCharsets.UTF_8),
+ stderr.toString(StandardCharsets.UTF_8)
+ );
+
+ } catch (Exception e) {
+ return new SshCommandResult(-1, "", e.getMessage());
+ } finally {
+ if (channel != null) channel.disconnect();
+ if (session != null) session.disconnect();
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/com/litoralregas/openvpn/ssh/SshTestController.java b/src/main/java/com/litoralregas/openvpn/ssh/SshTestController.java
new file mode 100644
index 0000000..e619bff
--- /dev/null
+++ b/src/main/java/com/litoralregas/openvpn/ssh/SshTestController.java
@@ -0,0 +1,25 @@
+package com.litoralregas.openvpn.ssh;
+
+import org.springframework.web.bind.annotation.*;
+
+@RestController
+@RequestMapping("/api/ssh-test")
+public class SshTestController {
+
+ private final SshService sshService;
+
+ public SshTestController(SshService sshService) {
+ this.sshService = sshService;
+ }
+
+ @PostMapping
+ public SshCommandResult test(@RequestBody SshTestRequest request) {
+ return sshService.execute(
+ request.host(),
+ request.port(),
+ request.username(),
+ request.password(),
+ "whoami && hostname"
+ );
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/com/litoralregas/openvpn/ssh/SshTestRequest.java b/src/main/java/com/litoralregas/openvpn/ssh/SshTestRequest.java
new file mode 100644
index 0000000..5d1e605
--- /dev/null
+++ b/src/main/java/com/litoralregas/openvpn/ssh/SshTestRequest.java
@@ -0,0 +1,9 @@
+package com.litoralregas.openvpn.ssh;
+
+public record SshTestRequest(
+ String host,
+ int port,
+ String username,
+ String password
+) {
+}
\ No newline at end of file