Add dry-run provisioning command generation
This commit is contained in:
@@ -2,6 +2,7 @@ package com.litoralregas.openvpn.openvpn;
|
||||
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
|
||||
import java.util.Optional;
|
||||
import java.util.UUID;
|
||||
|
||||
public interface IpAllocationRepository extends JpaRepository<IpAllocation, UUID> {
|
||||
@@ -11,4 +12,5 @@ public interface IpAllocationRepository extends JpaRepository<IpAllocation, UUID
|
||||
boolean existsByLanSubnet(String lanSubnet);
|
||||
|
||||
boolean existsByVpnIp(String vpnIp);
|
||||
Optional<IpAllocation> findByRouterId(UUID routerId);
|
||||
}
|
||||
@@ -113,4 +113,9 @@ public class IpAllocationService {
|
||||
public void delete(UUID id) {
|
||||
repository.deleteById(id);
|
||||
}
|
||||
|
||||
public IpAllocation findByRouterId(UUID routerId) {
|
||||
return repository.findByRouterId(routerId)
|
||||
.orElseThrow(() -> new IllegalArgumentException("No IP allocation found for router: " + routerId));
|
||||
}
|
||||
}
|
||||
@@ -64,4 +64,22 @@ public class OpenVpnService {
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public String buildProvisionCommand(String clientName, String lanSubnet, String vpnIp) {
|
||||
validateShellSafe(clientName);
|
||||
validateShellSafe(lanSubnet);
|
||||
validateShellSafe(vpnIp);
|
||||
|
||||
return properties.getToolsPath()
|
||||
+ "/provision-client.sh "
|
||||
+ clientName + " "
|
||||
+ lanSubnet + " "
|
||||
+ vpnIp;
|
||||
}
|
||||
|
||||
private void validateShellSafe(String value) {
|
||||
if (value == null || !value.matches("^[a-zA-Z0-9._/-]+$")) {
|
||||
throw new IllegalArgumentException("Unsafe command value: " + value);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -3,6 +3,8 @@ 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.*;
|
||||
@@ -17,11 +19,15 @@ 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) {
|
||||
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
|
||||
@@ -61,20 +67,22 @@ public class RouterController {
|
||||
try {
|
||||
service.forceStatus(id, RouterStatus.PROVISIONING);
|
||||
|
||||
var result = sshService.executeOnConfiguredVps(
|
||||
"echo 'Provisioning router: " + router.getName() + "' && whoami && hostname"
|
||||
);
|
||||
var allocation = ipAllocationService.findByRouterId(id);
|
||||
|
||||
if (result.exitCode() != 0) {
|
||||
throw new IllegalStateException(result.stderr());
|
||||
}
|
||||
String command = openVpnService.buildProvisionCommand(
|
||||
allocation.getClientName(),
|
||||
allocation.getLanSubnet(),
|
||||
allocation.getVpnIp()
|
||||
);
|
||||
|
||||
var finishedDeployment = deploymentService.finishSuccess(
|
||||
deployment,
|
||||
result.stdout()
|
||||
"DRY RUN ONLY. Would execute: " + command
|
||||
);
|
||||
|
||||
service.forceStatus(id, RouterStatus.REMOVING);
|
||||
// Keep this as PROVISIONING? No — dry run succeeded but real provision did not happen.
|
||||
// So we should NOT mark as PROVISIONED yet.
|
||||
service.forceStatus(id, RouterStatus.PENDING);
|
||||
|
||||
return DeploymentResponse.from(finishedDeployment);
|
||||
} catch (Exception exception) {
|
||||
|
||||
Reference in New Issue
Block a user