Add SSH command execution service
This commit is contained in:
@@ -65,6 +65,11 @@
|
|||||||
<artifactId>spring-boot-starter-test</artifactId>
|
<artifactId>spring-boot-starter-test</artifactId>
|
||||||
<scope>test</scope>
|
<scope>test</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.jcraft</groupId>
|
||||||
|
<artifactId>jsch</artifactId>
|
||||||
|
<version>0.1.55</version>
|
||||||
|
</dependency>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
|
||||||
<build>
|
<build>
|
||||||
|
|||||||
@@ -78,4 +78,34 @@ public class RouterController {
|
|||||||
return DeploymentResponse.from(failedDeployment);
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
package com.litoralregas.openvpn.ssh;
|
||||||
|
|
||||||
|
public record SshCommandResult(
|
||||||
|
int exitCode,
|
||||||
|
String stdout,
|
||||||
|
String stderr
|
||||||
|
) {
|
||||||
|
}
|
||||||
@@ -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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
package com.litoralregas.openvpn.ssh;
|
||||||
|
|
||||||
|
public record SshTestRequest(
|
||||||
|
String host,
|
||||||
|
int port,
|
||||||
|
String username,
|
||||||
|
String password
|
||||||
|
) {
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user