Files
lr-openvpn-backend/src/main/java/com/litoralregas/openvpn/router/RouterController.java
T

153 lines
5.0 KiB
Java

package com.litoralregas.openvpn.router;
import com.litoralregas.openvpn.deployment.DeploymentAction;
import com.litoralregas.openvpn.deployment.DeploymentResponse;
import com.litoralregas.openvpn.deployment.DeploymentService;
import com.litoralregas.openvpn.openvpn.IpAllocationService;
import com.litoralregas.openvpn.openvpn.OpenVpnService;
import com.litoralregas.openvpn.ssh.SshService;
import jakarta.validation.Valid;
import org.springframework.web.bind.annotation.*;
import java.util.List;
import java.util.UUID;
@RestController
@RequestMapping("/api/routers")
public class RouterController {
private final RouterService service;
private final DeploymentService deploymentService;
private final SshService sshService;
private final IpAllocationService ipAllocationService;
private final OpenVpnService openVpnService;
public RouterController(RouterService service, DeploymentService deploymentService, SshService sshService, IpAllocationService ipAllocationService, OpenVpnService openVpnService) {
this.service = service;
this.deploymentService = deploymentService;
this.sshService = sshService;
this.ipAllocationService = ipAllocationService;
this.openVpnService = openVpnService;
}
@GetMapping
public List<Router> getAll() {
return service.findAll();
}
@PostMapping
public Router create(@Valid @RequestBody CreateRouterRequest request) {
return service.create(request);
}
@GetMapping("/{id}")
public Router getById(@PathVariable UUID id) {
return service.findById(id);
}
@PatchMapping("/{id}/status")
public Router updateStatus(
@PathVariable UUID id,
@Valid @RequestBody UpdateRouterStatusRequest request
) {
return service.updateStatus(id, request);
}
@DeleteMapping("/{id}")
public void delete(@PathVariable UUID id) {
service.delete(id);
}
@PostMapping("/{id}/provision")
public DeploymentResponse provision(@PathVariable UUID id) {
Router router = service.findById(id);
var deployment = deploymentService.startDeployment(router, DeploymentAction.PROVISION);
try {
service.forceStatus(id, RouterStatus.PROVISIONING);
var allocation = ipAllocationService.findByRouterId(id);
var preflight = openVpnService.runPreflightCheck();
if (preflight.exitCode() != 0) {
throw new IllegalStateException(
"Preflight failed. stdout: " + preflight.stdout()
+ " stderr: " + preflight.stderr()
);
}
var result = openVpnService.provisionClient(
allocation.getClientName(),
allocation.getLanSubnet(),
allocation.getVpnIp()
);
if (result.exitCode() != 0) {
throw new IllegalStateException(
"Provision failed. stdout: " + result.stdout()
+ " stderr: " + result.stderr()
);
}
var finishedDeployment = deploymentService.finishSuccess(
deployment,
result.stdout()
);
if (openVpnService.isDryRun()) {
service.forceStatus(id, RouterStatus.PENDING);
} else {
service.forceStatus(id, RouterStatus.PROVISIONED);
}
return DeploymentResponse.from(finishedDeployment);
} catch (Exception exception) {
var failedDeployment = deploymentService.finishFailure(
deployment,
exception.getMessage()
);
service.forceStatus(id, RouterStatus.FAILED);
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
var result = sshService.executeOnConfiguredVps(
"echo 'Removing router: " + router.getName() + "' && whoami && hostname"
);
if (result.exitCode() != 0) {
throw new IllegalStateException(result.stderr());
}
var finished = deploymentService.finishSuccess(
deployment,
result.stdout()
);
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);
}
}
}